Mercurial > hg > truffle
comparison src/os/bsd/vm/os_bsd.cpp @ 7629:22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
Summary: misc correctness fixes
Reviewed-by: acorn, dholmes, dice, sspitsyn
Contributed-by: dave.dice@oracle.com
author | dcubed |
---|---|
date | Tue, 22 Jan 2013 05:56:42 -0800 |
parents | c07c102cbad7 |
children | 3ac7d10a6572 758935f7c23f |
comparison
equal
deleted
inserted
replaced
7628:f3184f32ce0b | 7629:22ba8c8ce6a6 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
4092 if (status == ETIMEDOUT) { status = EINTR; } | 4092 if (status == ETIMEDOUT) { status = EINTR; } |
4093 assert_status(status == 0 || status == EINTR, status, "cond_wait"); | 4093 assert_status(status == 0 || status == EINTR, status, "cond_wait"); |
4094 } | 4094 } |
4095 -- _nParked ; | 4095 -- _nParked ; |
4096 | 4096 |
4097 // In theory we could move the ST of 0 into _Event past the unlock(), | |
4098 // but then we'd need a MEMBAR after the ST. | |
4099 _Event = 0 ; | 4097 _Event = 0 ; |
4100 status = pthread_mutex_unlock(_mutex); | 4098 status = pthread_mutex_unlock(_mutex); |
4101 assert_status(status == 0, status, "mutex_unlock"); | 4099 assert_status(status == 0, status, "mutex_unlock"); |
4100 // Paranoia to ensure our locked and lock-free paths interact | |
4101 // correctly with each other. | |
4102 OrderAccess::fence(); | |
4102 } | 4103 } |
4103 guarantee (_Event >= 0, "invariant") ; | 4104 guarantee (_Event >= 0, "invariant") ; |
4104 } | 4105 } |
4105 | 4106 |
4106 int os::PlatformEvent::park(jlong millis) { | 4107 int os::PlatformEvent::park(jlong millis) { |
4159 } | 4160 } |
4160 _Event = 0 ; | 4161 _Event = 0 ; |
4161 status = pthread_mutex_unlock(_mutex); | 4162 status = pthread_mutex_unlock(_mutex); |
4162 assert_status(status == 0, status, "mutex_unlock"); | 4163 assert_status(status == 0, status, "mutex_unlock"); |
4163 assert (_nParked == 0, "invariant") ; | 4164 assert (_nParked == 0, "invariant") ; |
4165 // Paranoia to ensure our locked and lock-free paths interact | |
4166 // correctly with each other. | |
4167 OrderAccess::fence(); | |
4164 return ret; | 4168 return ret; |
4165 } | 4169 } |
4166 | 4170 |
4167 void os::PlatformEvent::unpark() { | 4171 void os::PlatformEvent::unpark() { |
4168 int v, AnyWaiters ; | 4172 // Transitions for _Event: |
4169 for (;;) { | 4173 // 0 :=> 1 |
4170 v = _Event ; | 4174 // 1 :=> 1 |
4171 if (v > 0) { | 4175 // -1 :=> either 0 or 1; must signal target thread |
4172 // The LD of _Event could have reordered or be satisfied | 4176 // That is, we can safely transition _Event from -1 to either |
4173 // by a read-aside from this processor's write buffer. | 4177 // 0 or 1. Forcing 1 is slightly more efficient for back-to-back |
4174 // To avoid problems execute a barrier and then | 4178 // unpark() calls. |
4175 // ratify the value. | 4179 // See also: "Semaphores in Plan 9" by Mullender & Cox |
4176 OrderAccess::fence() ; | 4180 // |
4177 if (_Event == v) return ; | 4181 // Note: Forcing a transition from "-1" to "1" on an unpark() means |
4178 continue ; | 4182 // that it will take two back-to-back park() calls for the owning |
4179 } | 4183 // thread to block. This has the benefit of forcing a spurious return |
4180 if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; | 4184 // from the first park() call after an unpark() call which will help |
4181 } | 4185 // shake out uses of park() and unpark() without condition variables. |
4182 if (v < 0) { | 4186 |
4183 // Wait for the thread associated with the event to vacate | 4187 if (Atomic::xchg(1, &_Event) >= 0) return; |
4184 int status = pthread_mutex_lock(_mutex); | 4188 |
4185 assert_status(status == 0, status, "mutex_lock"); | 4189 // Wait for the thread associated with the event to vacate |
4186 AnyWaiters = _nParked ; | 4190 int status = pthread_mutex_lock(_mutex); |
4187 assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; | 4191 assert_status(status == 0, status, "mutex_lock"); |
4188 if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { | 4192 int AnyWaiters = _nParked; |
4189 AnyWaiters = 0 ; | 4193 assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); |
4190 pthread_cond_signal (_cond); | 4194 if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { |
4191 } | 4195 AnyWaiters = 0; |
4192 status = pthread_mutex_unlock(_mutex); | 4196 pthread_cond_signal(_cond); |
4193 assert_status(status == 0, status, "mutex_unlock"); | 4197 } |
4194 if (AnyWaiters != 0) { | 4198 status = pthread_mutex_unlock(_mutex); |
4195 status = pthread_cond_signal(_cond); | 4199 assert_status(status == 0, status, "mutex_unlock"); |
4196 assert_status(status == 0, status, "cond_signal"); | 4200 if (AnyWaiters != 0) { |
4197 } | 4201 status = pthread_cond_signal(_cond); |
4202 assert_status(status == 0, status, "cond_signal"); | |
4198 } | 4203 } |
4199 | 4204 |
4200 // Note that we signal() _after dropping the lock for "immortal" Events. | 4205 // Note that we signal() _after dropping the lock for "immortal" Events. |
4201 // This is safe and avoids a common class of futile wakeups. In rare | 4206 // This is safe and avoids a common class of futile wakeups. In rare |
4202 // circumstances this can cause a thread to return prematurely from | 4207 // circumstances this can cause a thread to return prematurely from |
4278 assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); | 4283 assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); |
4279 assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); | 4284 assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); |
4280 } | 4285 } |
4281 | 4286 |
4282 void Parker::park(bool isAbsolute, jlong time) { | 4287 void Parker::park(bool isAbsolute, jlong time) { |
4288 // Ideally we'd do something useful while spinning, such | |
4289 // as calling unpackTime(). | |
4290 | |
4283 // Optional fast-path check: | 4291 // Optional fast-path check: |
4284 // Return immediately if a permit is available. | 4292 // Return immediately if a permit is available. |
4285 if (_counter > 0) { | 4293 // We depend on Atomic::xchg() having full barrier semantics |
4286 _counter = 0 ; | 4294 // since we are doing a lock-free update to _counter. |
4287 OrderAccess::fence(); | 4295 if (Atomic::xchg(0, &_counter) > 0) return; |
4288 return ; | |
4289 } | |
4290 | 4296 |
4291 Thread* thread = Thread::current(); | 4297 Thread* thread = Thread::current(); |
4292 assert(thread->is_Java_thread(), "Must be JavaThread"); | 4298 assert(thread->is_Java_thread(), "Must be JavaThread"); |
4293 JavaThread *jt = (JavaThread *)thread; | 4299 JavaThread *jt = (JavaThread *)thread; |
4294 | 4300 |
4325 int status ; | 4331 int status ; |
4326 if (_counter > 0) { // no wait needed | 4332 if (_counter > 0) { // no wait needed |
4327 _counter = 0; | 4333 _counter = 0; |
4328 status = pthread_mutex_unlock(_mutex); | 4334 status = pthread_mutex_unlock(_mutex); |
4329 assert (status == 0, "invariant") ; | 4335 assert (status == 0, "invariant") ; |
4336 // Paranoia to ensure our locked and lock-free paths interact | |
4337 // correctly with each other and Java-level accesses. | |
4330 OrderAccess::fence(); | 4338 OrderAccess::fence(); |
4331 return; | 4339 return; |
4332 } | 4340 } |
4333 | 4341 |
4334 #ifdef ASSERT | 4342 #ifdef ASSERT |
4361 #endif | 4369 #endif |
4362 | 4370 |
4363 _counter = 0 ; | 4371 _counter = 0 ; |
4364 status = pthread_mutex_unlock(_mutex) ; | 4372 status = pthread_mutex_unlock(_mutex) ; |
4365 assert_status(status == 0, status, "invariant") ; | 4373 assert_status(status == 0, status, "invariant") ; |
4374 // Paranoia to ensure our locked and lock-free paths interact | |
4375 // correctly with each other and Java-level accesses. | |
4376 OrderAccess::fence(); | |
4377 | |
4366 // If externally suspended while waiting, re-suspend | 4378 // If externally suspended while waiting, re-suspend |
4367 if (jt->handle_special_suspend_equivalent_condition()) { | 4379 if (jt->handle_special_suspend_equivalent_condition()) { |
4368 jt->java_suspend_self(); | 4380 jt->java_suspend_self(); |
4369 } | 4381 } |
4370 | |
4371 OrderAccess::fence(); | |
4372 } | 4382 } |
4373 | 4383 |
4374 void Parker::unpark() { | 4384 void Parker::unpark() { |
4375 int s, status ; | 4385 int s, status ; |
4376 status = pthread_mutex_lock(_mutex); | 4386 status = pthread_mutex_lock(_mutex); |