21 * questions.
22 *
23 */
24
25 #ifndef SHARE_UTILITIES_WAITBARRIER_HPP
26 #define SHARE_UTILITIES_WAITBARRIER_HPP
27
28 #include "memory/allocation.hpp"
29 #include "runtime/thread.hpp"
30 #include "utilities/debug.hpp"
31 #include "utilities/waitBarrier_generic.hpp"
32
33 #if defined(LINUX)
34 #include "waitBarrier_linux.hpp"
35 typedef LinuxWaitBarrier WaitBarrierDefault;
36 #else
37 typedef GenericWaitBarrier WaitBarrierDefault;
38 #endif
39
40 // Platform independent WaitBarrier API.
41 // An armed WaitBarrier prevents threads from advancing until the
42 // barrier is disarmed and the waiting threads woken. The barrier is
43 // armed by setting a non-zero value - the tag.
44 // When the WaitBarrier is created, a thread is designated the owner
45 // and is the thread that should arm/disarm/wake the WaitBarrier. In
46 // debug builds this is enforced.
47 //
48 // Expected Usage:
49 // - Arming thread:
50 // tag = ...; // non-zero value
51 // barrier.arm(tag);
52 // <publish tag>
53 // <work>
54 // barrier.disarm();
55 // barrier.wake();
56 //
57 // - After arm(tag) returns any thread calling wait(tag) will block.
58 // - After disarm() returns any subsequent calls to wait(tag) will not block.
59 // - After wake() returns all blocked threads are unblocked and eligible to
60 // execute again.
61 // - After calling disarm() and wake() the barrier is ready to be re-armed
62 // with a new tag. (may not be re-armed with last used tag)
63 //
64 // - Waiting threads
65 // wait(tag); // don't execute following code unless 'safe'
66 // <work>
67 //
68 // - A call to wait(tag) will block if the barrier is armed with the value
69 // 'tag'; else it will return immediately.
70 // - A blocked thread is eligible to execute again once the barrier is
71 // disarmed and wake() has been called.
72 //
73 // It is a usage error to:
74 // - call wake on a barrier that is still armed
75 // - call arm on a barrier that is already armed
76 // - call disarm on a barrier that is not armed
77 // - arm with the same tag as last used
78 // Usage errors are checked in debug builds but may be ignored otherwise.
79 //
80 // A primary goal of the WaitBarrier implementation is to wake all waiting
81 // threads as fast, and as concurrently, as possible.
82 //
83 template <typename WaitBarrierImpl>
84 class WaitBarrierType : public CHeapObj<mtInternal> {
85 WaitBarrierImpl _impl;
86
87 // Prevent copying and assignment of WaitBarrier instances.
88 WaitBarrierType(const WaitBarrierDefault&);
89 WaitBarrierType& operator=(const WaitBarrierDefault&);
90
91 #ifdef ASSERT
92 int _last_arm_tag;
93 Thread* _owner;
94 #endif
95
96 public:
99 _last_arm_tag = 0;
100 _owner = owner;
101 #endif
102 }
103 ~WaitBarrierType() {}
104
105 // Returns implementation type.
106 const char* description() { return _impl.description(); }
107
108 // Guarantees any thread calling wait() with same tag will be blocked.
109 // Provides a trailing fence.
110 void arm(int barrier_tag) {
111 #ifdef ASSERT
112 assert(_last_arm_tag != barrier_tag, "Re-arming with same tag");
113 _last_arm_tag = barrier_tag;
114 assert(_owner == Thread::current(), "Not owner thread");
115 #endif
116 _impl.arm(barrier_tag);
117 }
118
119 // Guarantees any thread calling wait() with any tag will not be blocked.
120 // Provides a trailing fence.
121 void disarm() {
122 assert(_owner == Thread::current(), "Not owner thread");
123 _impl.disarm();
124 }
125
126 // Guarantees any thread called wait() will be awake when it returns.
127 // Provides a trailing fence.
128 void wake() {
129 assert(_owner == Thread::current(), "Not owner thread");
130 _impl.wake();
131 }
132
133 // Guarantees not to return until disarm() is called,
134 // if called with currently armed tag (otherwise returns immediately).
135 // Implementations must guarantee no spurious wakeups.
136 // Guarantees to return if disarm() and wake() is called.
137 // Provides a trailing fence.
138 void wait(int barrier_tag) {
139 assert(_owner != Thread::current(), "Trying to wait with owner thread");
140 _impl.wait(barrier_tag);
141 }
142 };
143
144 typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier;
145
146 #endif // SHARE_UTILITIES_WAITBARRIER_HPP
|
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_UTILITIES_WAITBARRIER_HPP
26 #define SHARE_UTILITIES_WAITBARRIER_HPP
27
28 #include "memory/allocation.hpp"
29 #include "runtime/thread.hpp"
30 #include "utilities/debug.hpp"
31 #include "utilities/waitBarrier_generic.hpp"
32
33 #if defined(LINUX)
34 #include "waitBarrier_linux.hpp"
35 typedef LinuxWaitBarrier WaitBarrierDefault;
36 #else
37 typedef GenericWaitBarrier WaitBarrierDefault;
38 #endif
39
40 // Platform independent WaitBarrier API.
41 // An armed WaitBarrier prevents threads from advancing until the threads are
42 // woken by calling wake(). The barrier is armed by setting a non-zero value
43 // - the tag. When the WaitBarrier is created, a thread is designated the owner
44 // and is the thread that should arm and wake the WaitBarrier. In debug builds
45 // this is enforced.
46 //
47 // Expected Usage:
48 // - Arming thread:
49 // tag = ...; // non-zero value
50 // barrier.arm(tag);
51 // <publish tag>
52 // <work>
53 // barrier.wake();
54 //
55 // - After arm(tag) returns any thread calling wait(tag) will block.
56 // - Calling wake() guarantees any thread calling or called wait(tag) will
57 // return. Either they will see the WaitBarrier as disarmed or they will be
58 // unblocked and eligible to execute again when wake() returns.
59 // - After calling wake() the barrier is ready to be re-armed with a new tag.
60 // (may not be re-armed with last used tag)
61 //
62 // - Waiting threads
63 // wait(tag); // don't execute following code unless 'safe'
64 // <work>
65 //
66 // - A call to wait(tag) will block if the barrier is armed with the value
67 // 'tag'; else it will return immediately.
68 // - A blocked thread is eligible to execute again once the barrier is
69 // disarmed when wake() has been called.
70 //
71 // It is a usage error to:
72 // - call arm on a barrier that is already armed
73 // - call wake on a barrier that is not armed
74 // - arm with the same tag as last used
75 // Usage errors are checked in debug builds but may be ignored otherwise.
76 //
77 // A primary goal of the WaitBarrier implementation is to wake all waiting
78 // threads as fast, and as concurrently, as possible.
79 //
80 template <typename WaitBarrierImpl>
81 class WaitBarrierType : public CHeapObj<mtInternal> {
82 WaitBarrierImpl _impl;
83
84 // Prevent copying and assignment of WaitBarrier instances.
85 WaitBarrierType(const WaitBarrierDefault&);
86 WaitBarrierType& operator=(const WaitBarrierDefault&);
87
88 #ifdef ASSERT
89 int _last_arm_tag;
90 Thread* _owner;
91 #endif
92
93 public:
96 _last_arm_tag = 0;
97 _owner = owner;
98 #endif
99 }
100 ~WaitBarrierType() {}
101
102 // Returns implementation type.
103 const char* description() { return _impl.description(); }
104
105 // Guarantees any thread calling wait() with same tag will be blocked.
106 // Provides a trailing fence.
107 void arm(int barrier_tag) {
108 #ifdef ASSERT
109 assert(_last_arm_tag != barrier_tag, "Re-arming with same tag");
110 _last_arm_tag = barrier_tag;
111 assert(_owner == Thread::current(), "Not owner thread");
112 #endif
113 _impl.arm(barrier_tag);
114 }
115
116 // Guarantees any thread called wait() will be awake when it returns.
117 // Provides a trailing fence.
118 void wake() {
119 assert(_owner == Thread::current(), "Not owner thread");
120 _impl.wake();
121 }
122
123 // Guarantees not to return until wake() is called,
124 // if called with currently armed tag (otherwise returns immediately).
125 // Implementations must guarantee no spurious wakeups.
126 // Provides a trailing fence.
127 void wait(int barrier_tag) {
128 assert(_owner != Thread::current(), "Trying to wait with owner thread");
129 _impl.wait(barrier_tag);
130 }
131 };
132
133 typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier;
134
135 #endif // SHARE_UTILITIES_WAITBARRIER_HPP
|