1.1 --- a/src/os/bsd/vm/os_bsd.cpp Tue Jan 22 05:55:04 2013 -0800 1.2 +++ b/src/os/bsd/vm/os_bsd.cpp Tue Jan 22 05:56:42 2013 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -4094,11 +4094,12 @@ 1.11 } 1.12 -- _nParked ; 1.13 1.14 - // In theory we could move the ST of 0 into _Event past the unlock(), 1.15 - // but then we'd need a MEMBAR after the ST. 1.16 _Event = 0 ; 1.17 status = pthread_mutex_unlock(_mutex); 1.18 assert_status(status == 0, status, "mutex_unlock"); 1.19 + // Paranoia to ensure our locked and lock-free paths interact 1.20 + // correctly with each other. 1.21 + OrderAccess::fence(); 1.22 } 1.23 guarantee (_Event >= 0, "invariant") ; 1.24 } 1.25 @@ -4161,40 +4162,44 @@ 1.26 status = pthread_mutex_unlock(_mutex); 1.27 assert_status(status == 0, status, "mutex_unlock"); 1.28 assert (_nParked == 0, "invariant") ; 1.29 + // Paranoia to ensure our locked and lock-free paths interact 1.30 + // correctly with each other. 1.31 + OrderAccess::fence(); 1.32 return ret; 1.33 } 1.34 1.35 void os::PlatformEvent::unpark() { 1.36 - int v, AnyWaiters ; 1.37 - for (;;) { 1.38 - v = _Event ; 1.39 - if (v > 0) { 1.40 - // The LD of _Event could have reordered or be satisfied 1.41 - // by a read-aside from this processor's write buffer. 1.42 - // To avoid problems execute a barrier and then 1.43 - // ratify the value. 1.44 - OrderAccess::fence() ; 1.45 - if (_Event == v) return ; 1.46 - continue ; 1.47 - } 1.48 - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; 1.49 + // Transitions for _Event: 1.50 + // 0 :=> 1 1.51 + // 1 :=> 1 1.52 + // -1 :=> either 0 or 1; must signal target thread 1.53 + // That is, we can safely transition _Event from -1 to either 1.54 + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back 1.55 + // unpark() calls. 1.56 + // See also: "Semaphores in Plan 9" by Mullender & Cox 1.57 + // 1.58 + // Note: Forcing a transition from "-1" to "1" on an unpark() means 1.59 + // that it will take two back-to-back park() calls for the owning 1.60 + // thread to block. This has the benefit of forcing a spurious return 1.61 + // from the first park() call after an unpark() call which will help 1.62 + // shake out uses of park() and unpark() without condition variables. 1.63 + 1.64 + if (Atomic::xchg(1, &_Event) >= 0) return; 1.65 + 1.66 + // Wait for the thread associated with the event to vacate 1.67 + int status = pthread_mutex_lock(_mutex); 1.68 + assert_status(status == 0, status, "mutex_lock"); 1.69 + int AnyWaiters = _nParked; 1.70 + assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); 1.71 + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { 1.72 + AnyWaiters = 0; 1.73 + pthread_cond_signal(_cond); 1.74 } 1.75 - if (v < 0) { 1.76 - // Wait for the thread associated with the event to vacate 1.77 - int status = pthread_mutex_lock(_mutex); 1.78 - assert_status(status == 0, status, "mutex_lock"); 1.79 - AnyWaiters = _nParked ; 1.80 - assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; 1.81 - if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { 1.82 - AnyWaiters = 0 ; 1.83 - pthread_cond_signal (_cond); 1.84 - } 1.85 - status = pthread_mutex_unlock(_mutex); 1.86 - assert_status(status == 0, status, "mutex_unlock"); 1.87 - if (AnyWaiters != 0) { 1.88 - status = pthread_cond_signal(_cond); 1.89 - assert_status(status == 0, status, "cond_signal"); 1.90 - } 1.91 + status = pthread_mutex_unlock(_mutex); 1.92 + assert_status(status == 0, status, "mutex_unlock"); 1.93 + if (AnyWaiters != 0) { 1.94 + status = pthread_cond_signal(_cond); 1.95 + assert_status(status == 0, status, "cond_signal"); 1.96 } 1.97 1.98 // Note that we signal() _after dropping the lock for "immortal" Events. 1.99 @@ -4280,13 +4285,14 @@ 1.100 } 1.101 1.102 void Parker::park(bool isAbsolute, jlong time) { 1.103 + // Ideally we'd do something useful while spinning, such 1.104 + // as calling unpackTime(). 1.105 + 1.106 // Optional fast-path check: 1.107 // Return immediately if a permit is available. 1.108 - if (_counter > 0) { 1.109 - _counter = 0 ; 1.110 - OrderAccess::fence(); 1.111 - return ; 1.112 - } 1.113 + // We depend on Atomic::xchg() having full barrier semantics 1.114 + // since we are doing a lock-free update to _counter. 1.115 + if (Atomic::xchg(0, &_counter) > 0) return; 1.116 1.117 Thread* thread = Thread::current(); 1.118 assert(thread->is_Java_thread(), "Must be JavaThread"); 1.119 @@ -4327,6 +4333,8 @@ 1.120 _counter = 0; 1.121 status = pthread_mutex_unlock(_mutex); 1.122 assert (status == 0, "invariant") ; 1.123 + // Paranoia to ensure our locked and lock-free paths interact 1.124 + // correctly with each other and Java-level accesses. 1.125 OrderAccess::fence(); 1.126 return; 1.127 } 1.128 @@ -4363,12 +4371,14 @@ 1.129 _counter = 0 ; 1.130 status = pthread_mutex_unlock(_mutex) ; 1.131 assert_status(status == 0, status, "invariant") ; 1.132 + // Paranoia to ensure our locked and lock-free paths interact 1.133 + // correctly with each other and Java-level accesses. 1.134 + OrderAccess::fence(); 1.135 + 1.136 // If externally suspended while waiting, re-suspend 1.137 if (jt->handle_special_suspend_equivalent_condition()) { 1.138 jt->java_suspend_self(); 1.139 } 1.140 - 1.141 - OrderAccess::fence(); 1.142 } 1.143 1.144 void Parker::unpark() {