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 //
45 // Expected Usage:
46 // - Arming thread:
47 // tag = ...; // non-zero value
48 // barrier.arm(tag);
49 // <publish tag>
50 // <work>
51 // barrier.disarm();
52 // barrier.wake();
53 //
54 // - After arm(tag) returns any thread calling wait(tag) will block.
55 // - After disarm() returns any subsequent calls to wait(tag) will not block.
56 // - After wake() returns all blocked threads are unblocked and eligible to
57 // execute again.
58 // - After calling disarm() and wake() the barrier is ready to be re-armed
59 // with a new tag. (may not be re-armed with last used tag)
60 //
61 // - Waiting threads
62 // wait(tag); // don't execute following code unless 'safe'
63 // <work>
64 //
65 // - A call to wait(tag) will block if the barrier is armed with the value
66 // 'tag'; else it will return immediately.
67 // - A blocked thread is eligible to execute again once the barrier is
68 // disarmed and wake() has been called.
69 //
70 // A primary goal of the WaitBarrier implementation is to wake all waiting
71 // threads as fast, and as concurrently, as possible.
72 //
73 template <typename WaitBarrierImpl>
74 class WaitBarrierType : public CHeapObj<mtInternal> {
75 WaitBarrierImpl _impl;
76
77 // Prevent copying and assignment of WaitBarrier instances.
78 WaitBarrierType(const WaitBarrierDefault&);
79 WaitBarrierType& operator=(const WaitBarrierDefault&);
80
81 #ifdef ASSERT
82 int _last_arm_tag;
83 Thread* _owner;
84 #endif
85
86 public:
87 WaitBarrierType(Thread* owner) : _impl() {
88 #ifdef ASSERT
89 _last_arm_tag = 0;
103 _last_arm_tag = barrier_tag;
104 assert(_owner == Thread::current(), "Not owner thread");
105 #endif
106 _impl.arm(barrier_tag);
107 }
108
109 // Guarantees any thread calling wait() with any tag will not be blocked.
110 // Provides a trailing fence.
111 void disarm() {
112 assert(_owner == Thread::current(), "Not owner thread");
113 _impl.disarm();
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 to return if disarm() and wake() is called.
124 // Provides a trailing fence.
125 void wait(int barrier_tag) {
126 assert(_owner != Thread::current(), "Trying to wait with owner thread");
127 _impl.wait(barrier_tag);
128 }
129 };
130
131 typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier;
132
133 #endif // SHARE_UTILITIES_WAITBARRIER_HPP
|
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:
97 WaitBarrierType(Thread* owner) : _impl() {
98 #ifdef ASSERT
99 _last_arm_tag = 0;
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 // Implementation 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
|