< prev index next >
src/hotspot/share/utilities/waitBarrier.hpp
Print this page
rev 53038 : 8214271: Fast primitive to wake many threads
Reviewed-by:
rev 53039 : [mq]: 8214271-3
@@ -24,65 +24,110 @@
#ifndef SHARE_UTILITIES_WAITBARRIER_HPP
#define SHARE_UTILITIES_WAITBARRIER_HPP
#include "memory/allocation.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/debug.hpp"
#include "utilities/waitBarrier_generic.hpp"
#if defined(LINUX)
#include "waitBarrier_linux.hpp"
typedef LinuxWaitBarrier WaitBarrierDefault;
#else
typedef GenericWaitBarrier WaitBarrierDefault;
#endif
// Platform independent WaitBarrier API.
-// The WaitBarrier primary objective is to wake threads waiting in wait() fast.
-// It can be arm with any int, the tag, that is not 0.
-// - After arm() returns any thread calling wait(tag) with the correct tag will be blocked.
-// - After disarm() is called any thread calling wait(...) will never block.
-// - When wake() returns no threads are blocked any more, if it was disarmed before.
-// - After calling disarm() and wake() it my be re-armed immediately with a different tag.
-// - Re-arming with the same tag before all threads returned from previously wait
-// is implementation defined. They may or may not return from the previously wait().
-// Wake thread:
-// - arm(tag)
-// - *work*
-// - disarm()
-// - wake()
-// Wait thread:
-// - wait(tag)
+// An armed WaitBarrier prevents threads from advancing until the
+// barrier is disarmed and the waiting threads woken. The barrier is
+// armed by setting a non-zero value - the tag.
+//
+// Expected Usage:
+// - Arming thread:
+// tag = ...; // non-zero value
+// barrier.arm(tag);
+// <publish tag>
+// <work>
+// barrier.disarm();
+// barrier.wake();
+//
+// - After arm(tag) returns any thread calling wait(tag) will block.
+// - After disarm() returns any subsequent calls to wait(tag) will not block.
+// - After wake() returns all blocked threads are unblocked and eligible to
+// execute again.
+// - After calling disarm() and wake() the barrier is ready to be re-armed
+// with a new tag. (may not be re-armed with last used tag)
+//
+// - Waiting threads
+// wait(tag); // don't execute following code unless 'safe'
+// <work>
+//
+// - A call to wait(tag) will block if the barrier is armed with the value
+// 'tag'; else it will return immediately.
+// - A blocked thread is eligible to execute again once the barrier is
+// disarmed and wake() has been called.
+//
+// A primary goal of the WaitBarrier implementation is to wake all waiting
+// threads as fast, and as concurrently, as possible.
+//
template <typename WaitBarrierImpl>
class WaitBarrierType : public CHeapObj<mtInternal> {
WaitBarrierImpl _impl;
// Prevent copying and assignment of WaitBarrier instances.
WaitBarrierType(const WaitBarrierDefault&);
WaitBarrierType& operator=(const WaitBarrierDefault&);
+#ifdef ASSERT
+ int _last_arm_tag;
+ Thread* _owner;
+#endif
+
public:
- WaitBarrierType() : _impl() {}
+ WaitBarrierType(Thread* owner) : _impl() {
+#ifdef ASSERT
+ _last_arm_tag = 0;
+ _owner = owner;
+#endif
+ }
~WaitBarrierType() {}
// Returns implementation type.
const char* description() { return _impl.description(); }
// Guarantees any thread calling wait() with same tag will be blocked.
// Provides a trailing fence.
- void arm(int barrier_tag) { _impl.arm(barrier_tag); }
+ void arm(int barrier_tag) {
+#ifdef ASSERT
+ assert(_last_arm_tag != barrier_tag, "Re-arming with same tag");
+ _last_arm_tag = barrier_tag;
+ assert(_owner == Thread::current(), "Not owner thread");
+#endif
+ _impl.arm(barrier_tag);
+ }
// Guarantees any thread calling wait() with any tag will not be blocked.
// Provides a trailing fence.
- void disarm() { _impl.disarm(); }
+ void disarm() {
+ assert(_owner == Thread::current(), "Not owner thread");
+ _impl.disarm();
+ }
// Guarantees any thread called wait() will be awake when it returns.
// Provides a trailing fence.
- void wake() { _impl.wake(); }
+ void wake() {
+ assert(_owner == Thread::current(), "Not owner thread");
+ _impl.wake();
+ }
// Guarantees to return if disarm() and wake() is called.
// Provides a trailing fence.
- void wait(int barrier_tag) { _impl.wait(barrier_tag); }
+ void wait(int barrier_tag) {
+ assert(_owner != Thread::current(), "Trying to wait with owner thread");
+ _impl.wait(barrier_tag);
+ }
};
typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier;
#endif // SHARE_UTILITIES_WAITBARRIER_HPP
< prev index next >