src/hotspot/share/utilities/waitBarrier.hpp
author mr
Tue, 29 Oct 2019 08:26:55 -0700
changeset 58842 6c255334120d
parent 53254 47bc06170313
permissions -rw-r--r--
8232080: jlink plugins for vendor information and run-time options Reviewed-by: ihse, alanb, kvn, bobv, mchung
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     1
/*
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     2
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     4
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     7
 * published by the Free Software Foundation.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     8
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    13
 * accompanied this code).
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    14
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    18
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    21
 * questions.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    22
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    23
 */
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    24
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    25
#ifndef SHARE_UTILITIES_WAITBARRIER_HPP
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    26
#define SHARE_UTILITIES_WAITBARRIER_HPP
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    27
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    28
#include "memory/allocation.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    29
#include "runtime/thread.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    30
#include "utilities/debug.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    31
#include "utilities/waitBarrier_generic.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    32
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    33
#if defined(LINUX)
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    34
#include "waitBarrier_linux.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    35
typedef LinuxWaitBarrier WaitBarrierDefault;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    36
#else
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    37
typedef GenericWaitBarrier WaitBarrierDefault;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    38
#endif
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    39
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    40
// Platform independent WaitBarrier API.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    41
// An armed WaitBarrier prevents threads from advancing until the threads are
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    42
// woken by calling disarm(). The barrier is armed by setting a non-zero value
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    43
// - the tag. When the WaitBarrier is created, a thread is designated the owner
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    44
// and is the thread that should arm and disarm the WaitBarrier. In debug builds
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    45
// this is enforced.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    46
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    47
// Expected Usage:
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    48
//  - Arming thread:
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    49
//     tag = ...;  // non-zero value
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    50
//     barrier.arm(tag);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    51
//     <publish tag>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    52
//     <work>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    53
//     barrier.disarm();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    54
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    55
//    - After arm(tag) returns any thread calling wait(tag) will block.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    56
//    - Calling disarm() guarantees any thread calling or that has wait(tag) will
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    57
//      return. Either they will see the WaitBarrier as disarmed or they will be
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    58
//      unblocked and eligible to execute again when disarm() returns.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    59
//    - After calling disarm() the barrier is ready to be re-armed with a new tag.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    60
//      (may not be re-armed with last used tag)
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    61
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    62
//  - Waiting threads
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    63
//     wait(tag); // don't execute following code unless 'safe'
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    64
//     <work>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    65
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    66
//    - A call to wait(tag) will block if the barrier is armed with the value
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    67
//      'tag'; else it will return immediately.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    68
//    - A blocked thread is eligible to execute again once the barrier is
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    69
//      disarmed when disarm() has been called.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    70
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    71
// It is a usage error to:
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    72
//  - call arm on a barrier that is already armed
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    73
//  - call disarm on a barrier that is not armed
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    74
//  - arm with the same tag as last used
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    75
// Usage errors are checked in debug builds but may be ignored otherwise.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    76
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    77
// A primary goal of the WaitBarrier implementation is to wake all waiting
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    78
// threads as fast, and as concurrently, as possible.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    79
//
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    80
template <typename WaitBarrierImpl>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    81
class WaitBarrierType : public CHeapObj<mtInternal> {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    82
  WaitBarrierImpl _impl;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    83
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    84
  // Prevent copying and assignment of WaitBarrier instances.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    85
  WaitBarrierType(const WaitBarrierDefault&);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    86
  WaitBarrierType& operator=(const WaitBarrierDefault&);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    87
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    88
#ifdef ASSERT
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    89
  int _last_arm_tag;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    90
  Thread* _owner;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    91
#endif
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    92
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    93
 public:
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    94
  WaitBarrierType(Thread* owner) : _impl() {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    95
#ifdef ASSERT
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    96
    _last_arm_tag = 0;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    97
    _owner = owner;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    98
#endif
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    99
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   100
  ~WaitBarrierType() {}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   101
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   102
  // Returns implementation description.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   103
  const char* description()    { return _impl.description(); }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   104
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   105
  // Guarantees any thread calling wait() with same tag will be blocked.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   106
  // Provides a trailing fence.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   107
  void arm(int barrier_tag) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   108
#ifdef ASSERT
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   109
    assert(_last_arm_tag != barrier_tag, "Re-arming with same tag");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   110
    _last_arm_tag = barrier_tag;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   111
    assert(_owner == Thread::current(), "Not owner thread");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   112
#endif
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   113
    _impl.arm(barrier_tag);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   114
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   115
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   116
  // Guarantees any thread that called wait() will be awake when it returns.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   117
  // Provides a trailing fence.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   118
  void disarm() {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   119
    assert(_owner == Thread::current(), "Not owner thread");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   120
    _impl.disarm();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   121
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   122
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   123
  // Guarantees not to return until disarm() is called,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   124
  // if called with currently armed tag (otherwise returns immediately).
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   125
  // Implementations must guarantee no spurious wakeups.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   126
  // Provides a trailing fence.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   127
  void wait(int barrier_tag) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   128
    assert(_owner != Thread::current(), "Trying to wait with owner thread");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   129
    _impl.wait(barrier_tag);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   130
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   131
};
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   132
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   133
typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   134
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   135
#endif // SHARE_UTILITIES_WAITBARRIER_HPP