6053 -- _nParked ; |
6056 -- _nParked ; |
6054 if (_Event >= 0) ret = OS_OK ; |
6057 if (_Event >= 0) ret = OS_OK ; |
6055 _Event = 0 ; |
6058 _Event = 0 ; |
6056 status = os::Solaris::mutex_unlock(_mutex); |
6059 status = os::Solaris::mutex_unlock(_mutex); |
6057 assert_status(status == 0, status, "mutex_unlock"); |
6060 assert_status(status == 0, status, "mutex_unlock"); |
|
6061 // Paranoia to ensure our locked and lock-free paths interact |
|
6062 // correctly with each other. |
|
6063 OrderAccess::fence(); |
6058 return ret; |
6064 return ret; |
6059 } |
6065 } |
6060 |
6066 |
6061 void os::PlatformEvent::unpark() { |
6067 void os::PlatformEvent::unpark() { |
6062 int v, AnyWaiters; |
6068 // Transitions for _Event: |
6063 |
6069 // 0 :=> 1 |
6064 // Increment _Event. |
6070 // 1 :=> 1 |
6065 // Another acceptable implementation would be to simply swap 1 |
6071 // -1 :=> either 0 or 1; must signal target thread |
6066 // into _Event: |
6072 // That is, we can safely transition _Event from -1 to either |
6067 // if (Swap (&_Event, 1) < 0) { |
6073 // 0 or 1. Forcing 1 is slightly more efficient for back-to-back |
6068 // mutex_lock (_mutex) ; AnyWaiters = nParked; mutex_unlock (_mutex) ; |
6074 // unpark() calls. |
6069 // if (AnyWaiters) cond_signal (_cond) ; |
6075 // See also: "Semaphores in Plan 9" by Mullender & Cox |
6070 // } |
6076 // |
6071 |
6077 // Note: Forcing a transition from "-1" to "1" on an unpark() means |
6072 for (;;) { |
6078 // that it will take two back-to-back park() calls for the owning |
6073 v = _Event ; |
6079 // thread to block. This has the benefit of forcing a spurious return |
6074 if (v > 0) { |
6080 // from the first park() call after an unpark() call which will help |
6075 // The LD of _Event could have reordered or be satisfied |
6081 // shake out uses of park() and unpark() without condition variables. |
6076 // by a read-aside from this processor's write buffer. |
6082 |
6077 // To avoid problems execute a barrier and then |
6083 if (Atomic::xchg(1, &_Event) >= 0) return; |
6078 // ratify the value. A degenerate CAS() would also work. |
|
6079 // Viz., CAS (v+0, &_Event, v) == v). |
|
6080 OrderAccess::fence() ; |
|
6081 if (_Event == v) return ; |
|
6082 continue ; |
|
6083 } |
|
6084 if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; |
|
6085 } |
|
6086 |
6084 |
6087 // If the thread associated with the event was parked, wake it. |
6085 // If the thread associated with the event was parked, wake it. |
6088 if (v < 0) { |
6086 // Wait for the thread assoc with the PlatformEvent to vacate. |
6089 int status ; |
6087 int status = os::Solaris::mutex_lock(_mutex); |
6090 // Wait for the thread assoc with the PlatformEvent to vacate. |
6088 assert_status(status == 0, status, "mutex_lock"); |
6091 status = os::Solaris::mutex_lock(_mutex); |
6089 int AnyWaiters = _nParked; |
6092 assert_status(status == 0, status, "mutex_lock"); |
6090 status = os::Solaris::mutex_unlock(_mutex); |
6093 AnyWaiters = _nParked ; |
6091 assert_status(status == 0, status, "mutex_unlock"); |
6094 status = os::Solaris::mutex_unlock(_mutex); |
6092 guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); |
6095 assert_status(status == 0, status, "mutex_unlock"); |
6093 if (AnyWaiters != 0) { |
6096 guarantee (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; |
6094 // We intentional signal *after* dropping the lock |
6097 if (AnyWaiters != 0) { |
6095 // to avoid a common class of futile wakeups. |
6098 // We intentional signal *after* dropping the lock |
6096 status = os::Solaris::cond_signal(_cond); |
6099 // to avoid a common class of futile wakeups. |
6097 assert_status(status == 0, status, "cond_signal"); |
6100 status = os::Solaris::cond_signal(_cond); |
|
6101 assert_status(status == 0, status, "cond_signal"); |
|
6102 } |
|
6103 } |
6098 } |
6104 } |
6099 } |
6105 |
6100 |
6106 // JSR166 |
6101 // JSR166 |
6107 // ------------------------------------------------------- |
6102 // ------------------------------------------------------- |
6175 assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); |
6170 assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); |
6176 assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); |
6171 assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); |
6177 } |
6172 } |
6178 |
6173 |
6179 void Parker::park(bool isAbsolute, jlong time) { |
6174 void Parker::park(bool isAbsolute, jlong time) { |
|
6175 // Ideally we'd do something useful while spinning, such |
|
6176 // as calling unpackTime(). |
6180 |
6177 |
6181 // Optional fast-path check: |
6178 // Optional fast-path check: |
6182 // Return immediately if a permit is available. |
6179 // Return immediately if a permit is available. |
6183 if (_counter > 0) { |
6180 // We depend on Atomic::xchg() having full barrier semantics |
6184 _counter = 0 ; |
6181 // since we are doing a lock-free update to _counter. |
6185 OrderAccess::fence(); |
6182 if (Atomic::xchg(0, &_counter) > 0) return; |
6186 return ; |
|
6187 } |
|
6188 |
6183 |
6189 // Optional fast-exit: Check interrupt before trying to wait |
6184 // Optional fast-exit: Check interrupt before trying to wait |
6190 Thread* thread = Thread::current(); |
6185 Thread* thread = Thread::current(); |
6191 assert(thread->is_Java_thread(), "Must be JavaThread"); |
6186 assert(thread->is_Java_thread(), "Must be JavaThread"); |
6192 JavaThread *jt = (JavaThread *)thread; |
6187 JavaThread *jt = (JavaThread *)thread; |
6265 thr_sigsetmask(SIG_SETMASK, &oldsigs, NULL); |
6262 thr_sigsetmask(SIG_SETMASK, &oldsigs, NULL); |
6266 #endif |
6263 #endif |
6267 _counter = 0 ; |
6264 _counter = 0 ; |
6268 status = os::Solaris::mutex_unlock(_mutex); |
6265 status = os::Solaris::mutex_unlock(_mutex); |
6269 assert_status(status == 0, status, "mutex_unlock") ; |
6266 assert_status(status == 0, status, "mutex_unlock") ; |
|
6267 // Paranoia to ensure our locked and lock-free paths interact |
|
6268 // correctly with each other and Java-level accesses. |
|
6269 OrderAccess::fence(); |
6270 |
6270 |
6271 // If externally suspended while waiting, re-suspend |
6271 // If externally suspended while waiting, re-suspend |
6272 if (jt->handle_special_suspend_equivalent_condition()) { |
6272 if (jt->handle_special_suspend_equivalent_condition()) { |
6273 jt->java_suspend_self(); |
6273 jt->java_suspend_self(); |
6274 } |
6274 } |
6275 OrderAccess::fence(); |
|
6276 } |
6275 } |
6277 |
6276 |
6278 void Parker::unpark() { |
6277 void Parker::unpark() { |
6279 int s, status ; |
6278 int s, status ; |
6280 status = os::Solaris::mutex_lock (_mutex) ; |
6279 status = os::Solaris::mutex_lock (_mutex) ; |