< prev index next >

src/hotspot/share/utilities/singleWriterSynchronizer.cpp

Print this page




  27 #include "runtime/orderAccess.hpp"
  28 #include "runtime/os.hpp"
  29 #include "utilities/debug.hpp"
  30 #include "utilities/singleWriterSynchronizer.hpp"
  31 #include "utilities/macros.hpp"
  32 
  33 SingleWriterSynchronizer::SingleWriterSynchronizer() :
  34   _enter(0),
  35   _exit(),
  36   // The initial value of 1 for _waiting_for puts it on the inactive
  37   // track, so no thread exiting a critical section will match it.
  38   _waiting_for(1),
  39   _wakeup()
  40   DEBUG_ONLY(COMMA _writers(0))
  41 {}
  42 
  43 // Wait until all threads that entered a critical section before
  44 // synchronization have exited that critical section.
  45 void SingleWriterSynchronizer::synchronize() {
  46   // Side-effect in assert balanced by debug-only dec at end.
  47   assert(Atomic::add(1u, &_writers) == 1u, "multiple writers");
  48   // We don't know anything about the muxing between this invocation
  49   // and invocations in other threads.  We must start with the latest
  50   // _enter polarity, else we could clobber the wrong _exit value on
  51   // the first iteration.  So fence to ensure everything here follows
  52   // whatever muxing was used.
  53   OrderAccess::fence();
  54   uint value = _enter;
  55   // (1) Determine the old and new exit counters, based on the
  56   // polarity (bit0 value) of the on-entry enter counter.
  57   volatile uint* new_ptr = &_exit[(value + 1) & 1];
  58   // (2) Change the in-use exit counter to the new counter, by adding
  59   // 1 to the enter counter (flipping the polarity), meanwhile
  60   // "simultaneously" initializing the new exit counter to that enter
  61   // value.  Note: The new exit counter is not being used by read
  62   // operations until this change of _enter succeeds.
  63   uint old;
  64   do {
  65     old = value;
  66     *new_ptr = ++value;
  67     value = Atomic::cmpxchg(value, &_enter, old);




  27 #include "runtime/orderAccess.hpp"
  28 #include "runtime/os.hpp"
  29 #include "utilities/debug.hpp"
  30 #include "utilities/singleWriterSynchronizer.hpp"
  31 #include "utilities/macros.hpp"
  32 
  33 SingleWriterSynchronizer::SingleWriterSynchronizer() :
  34   _enter(0),
  35   _exit(),
  36   // The initial value of 1 for _waiting_for puts it on the inactive
  37   // track, so no thread exiting a critical section will match it.
  38   _waiting_for(1),
  39   _wakeup()
  40   DEBUG_ONLY(COMMA _writers(0))
  41 {}
  42 
  43 // Wait until all threads that entered a critical section before
  44 // synchronization have exited that critical section.
  45 void SingleWriterSynchronizer::synchronize() {
  46   // Side-effect in assert balanced by debug-only dec at end.
  47   assert(Atomic::add(&_writers, 1u) == 1u, "multiple writers");
  48   // We don't know anything about the muxing between this invocation
  49   // and invocations in other threads.  We must start with the latest
  50   // _enter polarity, else we could clobber the wrong _exit value on
  51   // the first iteration.  So fence to ensure everything here follows
  52   // whatever muxing was used.
  53   OrderAccess::fence();
  54   uint value = _enter;
  55   // (1) Determine the old and new exit counters, based on the
  56   // polarity (bit0 value) of the on-entry enter counter.
  57   volatile uint* new_ptr = &_exit[(value + 1) & 1];
  58   // (2) Change the in-use exit counter to the new counter, by adding
  59   // 1 to the enter counter (flipping the polarity), meanwhile
  60   // "simultaneously" initializing the new exit counter to that enter
  61   // value.  Note: The new exit counter is not being used by read
  62   // operations until this change of _enter succeeds.
  63   uint old;
  64   do {
  65     old = value;
  66     *new_ptr = ++value;
  67     value = Atomic::cmpxchg(value, &_enter, old);


< prev index next >