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);
|