--- a/hotspot/src/os/windows/vm/os_windows.cpp Tue Jan 22 05:55:04 2013 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Tue Jan 22 05:56:42 2013 -0800
@@ -4565,6 +4565,7 @@
}
v = _Event ;
_Event = 0 ;
+ // see comment at end of os::PlatformEvent::park() below:
OrderAccess::fence() ;
// If we encounter a nearly simultanous timeout expiry and unpark()
// we return OS_OK indicating we awoke via unpark().
@@ -4602,25 +4603,25 @@
void os::PlatformEvent::unpark() {
guarantee (_ParkHandle != NULL, "Invariant") ;
- int v ;
- for (;;) {
- v = _Event ; // Increment _Event if it's < 1.
- if (v > 0) {
- // If it's already signaled just return.
- // The LD of _Event could have reordered or be satisfied
- // by a read-aside from this processor's write buffer.
- // To avoid problems execute a barrier and then
- // ratify the value. A degenerate CAS() would also work.
- // Viz., CAS (v+0, &_Event, v) == v).
- OrderAccess::fence() ;
- if (_Event == v) return ;
- continue ;
- }
- if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ;
- }
- if (v < 0) {
- ::SetEvent (_ParkHandle) ;
- }
+
+ // Transitions for _Event:
+ // 0 :=> 1
+ // 1 :=> 1
+ // -1 :=> either 0 or 1; must signal target thread
+ // That is, we can safely transition _Event from -1 to either
+ // 0 or 1. Forcing 1 is slightly more efficient for back-to-back
+ // unpark() calls.
+ // See also: "Semaphores in Plan 9" by Mullender & Cox
+ //
+ // Note: Forcing a transition from "-1" to "1" on an unpark() means
+ // that it will take two back-to-back park() calls for the owning
+ // thread to block. This has the benefit of forcing a spurious return
+ // from the first park() call after an unpark() call which will help
+ // shake out uses of park() and unpark() without condition variables.
+
+ if (Atomic::xchg(1, &_Event) >= 0) return;
+
+ ::SetEvent(_ParkHandle);
}