1.1 --- a/src/os/linux/vm/os_linux.cpp Tue Jan 22 05:55:04 2013 -0800 1.2 +++ b/src/os/linux/vm/os_linux.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 @@ -5001,11 +5001,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 @@ -5068,40 +5069,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 - } 1.50 - if (v < 0) { 1.51 - // Wait for the thread associated with the event to vacate 1.52 - int status = pthread_mutex_lock(_mutex); 1.53 - assert_status(status == 0, status, "mutex_lock"); 1.54 - AnyWaiters = _nParked ; 1.55 - assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; 1.56 - if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { 1.57 - AnyWaiters = 0 ; 1.58 - pthread_cond_signal (_cond); 1.59 - } 1.60 - status = pthread_mutex_unlock(_mutex); 1.61 - assert_status(status == 0, status, "mutex_unlock"); 1.62 - if (AnyWaiters != 0) { 1.63 - status = pthread_cond_signal(_cond); 1.64 - assert_status(status == 0, status, "cond_signal"); 1.65 - } 1.66 + // Transitions for _Event: 1.67 + // 0 :=> 1 1.68 + // 1 :=> 1 1.69 + // -1 :=> either 0 or 1; must signal target thread 1.70 + // That is, we can safely transition _Event from -1 to either 1.71 + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back 1.72 + // unpark() calls. 1.73 + // See also: "Semaphores in Plan 9" by Mullender & Cox 1.74 + // 1.75 + // Note: Forcing a transition from "-1" to "1" on an unpark() means 1.76 + // that it will take two back-to-back park() calls for the owning 1.77 + // thread to block. This has the benefit of forcing a spurious return 1.78 + // from the first park() call after an unpark() call which will help 1.79 + // shake out uses of park() and unpark() without condition variables. 1.80 + 1.81 + if (Atomic::xchg(1, &_Event) >= 0) return; 1.82 + 1.83 + // Wait for the thread associated with the event to vacate 1.84 + int status = pthread_mutex_lock(_mutex); 1.85 + assert_status(status == 0, status, "mutex_lock"); 1.86 + int AnyWaiters = _nParked; 1.87 + assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); 1.88 + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { 1.89 + AnyWaiters = 0; 1.90 + pthread_cond_signal(_cond); 1.91 + } 1.92 + status = pthread_mutex_unlock(_mutex); 1.93 + assert_status(status == 0, status, "mutex_unlock"); 1.94 + if (AnyWaiters != 0) { 1.95 + status = pthread_cond_signal(_cond); 1.96 + assert_status(status == 0, status, "cond_signal"); 1.97 } 1.98 1.99 // Note that we signal() _after dropping the lock for "immortal" Events. 1.100 @@ -5187,13 +5192,14 @@ 1.101 } 1.102 1.103 void Parker::park(bool isAbsolute, jlong time) { 1.104 + // Ideally we'd do something useful while spinning, such 1.105 + // as calling unpackTime(). 1.106 + 1.107 // Optional fast-path check: 1.108 // Return immediately if a permit is available. 1.109 - if (_counter > 0) { 1.110 - _counter = 0 ; 1.111 - OrderAccess::fence(); 1.112 - return ; 1.113 - } 1.114 + // We depend on Atomic::xchg() having full barrier semantics 1.115 + // since we are doing a lock-free update to _counter. 1.116 + if (Atomic::xchg(0, &_counter) > 0) return; 1.117 1.118 Thread* thread = Thread::current(); 1.119 assert(thread->is_Java_thread(), "Must be JavaThread"); 1.120 @@ -5234,6 +5240,8 @@ 1.121 _counter = 0; 1.122 status = pthread_mutex_unlock(_mutex); 1.123 assert (status == 0, "invariant") ; 1.124 + // Paranoia to ensure our locked and lock-free paths interact 1.125 + // correctly with each other and Java-level accesses. 1.126 OrderAccess::fence(); 1.127 return; 1.128 } 1.129 @@ -5270,12 +5278,14 @@ 1.130 _counter = 0 ; 1.131 status = pthread_mutex_unlock(_mutex) ; 1.132 assert_status(status == 0, status, "invariant") ; 1.133 + // Paranoia to ensure our locked and lock-free paths interact 1.134 + // correctly with each other and Java-level accesses. 1.135 + OrderAccess::fence(); 1.136 + 1.137 // If externally suspended while waiting, re-suspend 1.138 if (jt->handle_special_suspend_equivalent_condition()) { 1.139 jt->java_suspend_self(); 1.140 } 1.141 - 1.142 - OrderAccess::fence(); 1.143 } 1.144 1.145 void Parker::unpark() {