1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "runtime/atomic.hpp" 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(&_enter, old, value); 68 } while (old != value); 69 // Critical sections entered before we changed the polarity will use 70 // the old exit counter. Critical sections entered after the change 71 // will use the new exit counter. 72 volatile uint* old_ptr = &_exit[old & 1]; 73 assert(old_ptr != new_ptr, "invariant"); 74 // (3) Inform threads in in-progress critical sections that there is 75 // a pending synchronize waiting. The thread that completes the 76 // request (_exit value == old) will signal the _wakeup semaphore to 77 // allow us to proceed. 78 _waiting_for = old; 79 // Write of _waiting_for must precede read of _exit and associated 80 // conditional semaphore wait. If they were re-ordered then a 81 // critical section exit could miss the wakeup request, failing to 82 // signal us while we're waiting. 83 OrderAccess::fence(); 84 // (4) Wait for all the critical sections started before the change 85 // to complete, e.g. for the value of old_ptr to catch up with old. 86 // Loop because there could be pending wakeups unrelated to this 87 // synchronize request. 88 while (old != Atomic::load_acquire(old_ptr)) { 89 _wakeup.wait(); 90 } 91 // (5) Drain any pending wakeups. A critical section exit may have 92 // completed our request and seen our _waiting_for before we checked 93 // for completion. There are also possible (though rare) spurious 94 // wakeup signals in the timing gap between changing the _enter 95 // polarity and setting _waiting_for. Enough of any of those could 96 // lead to semaphore overflow. This doesn't guarantee no unrelated 97 // wakeups for the next wait, but prevents unbounded accumulation. 98 while (_wakeup.trywait()) {} 99 DEBUG_ONLY(Atomic::dec(&_writers);) 100 }