提交 01c35675 编写于 作者: D dcubed

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
上级 4d3a4fef
/* /*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -4094,11 +4094,12 @@ void os::PlatformEvent::park() { // AKA "down()" ...@@ -4094,11 +4094,12 @@ void os::PlatformEvent::park() { // AKA "down()"
} }
-- _nParked ; -- _nParked ;
// In theory we could move the ST of 0 into _Event past the unlock(),
// but then we'd need a MEMBAR after the ST.
_Event = 0 ; _Event = 0 ;
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
} }
guarantee (_Event >= 0, "invariant") ; guarantee (_Event >= 0, "invariant") ;
} }
...@@ -4161,33 +4162,38 @@ int os::PlatformEvent::park(jlong millis) { ...@@ -4161,33 +4162,38 @@ int os::PlatformEvent::park(jlong millis) {
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
assert (_nParked == 0, "invariant") ; assert (_nParked == 0, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
return ret; return ret;
} }
void os::PlatformEvent::unpark() { void os::PlatformEvent::unpark() {
int v, AnyWaiters ; // Transitions for _Event:
for (;;) { // 0 :=> 1
v = _Event ; // 1 :=> 1
if (v > 0) { // -1 :=> either 0 or 1; must signal target thread
// The LD of _Event could have reordered or be satisfied // That is, we can safely transition _Event from -1 to either
// by a read-aside from this processor's write buffer. // 0 or 1. Forcing 1 is slightly more efficient for back-to-back
// To avoid problems execute a barrier and then // unpark() calls.
// ratify the value. // See also: "Semaphores in Plan 9" by Mullender & Cox
OrderAccess::fence() ; //
if (_Event == v) return ; // Note: Forcing a transition from "-1" to "1" on an unpark() means
continue ; // 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
if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; // from the first park() call after an unpark() call which will help
} // shake out uses of park() and unpark() without condition variables.
if (v < 0) {
if (Atomic::xchg(1, &_Event) >= 0) return;
// Wait for the thread associated with the event to vacate // Wait for the thread associated with the event to vacate
int status = pthread_mutex_lock(_mutex); int status = pthread_mutex_lock(_mutex);
assert_status(status == 0, status, "mutex_lock"); assert_status(status == 0, status, "mutex_lock");
AnyWaiters = _nParked ; int AnyWaiters = _nParked;
assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
AnyWaiters = 0 ; AnyWaiters = 0;
pthread_cond_signal (_cond); pthread_cond_signal(_cond);
} }
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
...@@ -4195,7 +4201,6 @@ void os::PlatformEvent::unpark() { ...@@ -4195,7 +4201,6 @@ void os::PlatformEvent::unpark() {
status = pthread_cond_signal(_cond); status = pthread_cond_signal(_cond);
assert_status(status == 0, status, "cond_signal"); assert_status(status == 0, status, "cond_signal");
} }
}
// Note that we signal() _after dropping the lock for "immortal" Events. // Note that we signal() _after dropping the lock for "immortal" Events.
// This is safe and avoids a common class of futile wakeups. In rare // This is safe and avoids a common class of futile wakeups. In rare
...@@ -4280,13 +4285,14 @@ static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) { ...@@ -4280,13 +4285,14 @@ static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) {
} }
void Parker::park(bool isAbsolute, jlong time) { void Parker::park(bool isAbsolute, jlong time) {
// Ideally we'd do something useful while spinning, such
// as calling unpackTime().
// Optional fast-path check: // Optional fast-path check:
// Return immediately if a permit is available. // Return immediately if a permit is available.
if (_counter > 0) { // We depend on Atomic::xchg() having full barrier semantics
_counter = 0 ; // since we are doing a lock-free update to _counter.
OrderAccess::fence(); if (Atomic::xchg(0, &_counter) > 0) return;
return ;
}
Thread* thread = Thread::current(); Thread* thread = Thread::current();
assert(thread->is_Java_thread(), "Must be JavaThread"); assert(thread->is_Java_thread(), "Must be JavaThread");
...@@ -4327,6 +4333,8 @@ void Parker::park(bool isAbsolute, jlong time) { ...@@ -4327,6 +4333,8 @@ void Parker::park(bool isAbsolute, jlong time) {
_counter = 0; _counter = 0;
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert (status == 0, "invariant") ; assert (status == 0, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence(); OrderAccess::fence();
return; return;
} }
...@@ -4363,12 +4371,14 @@ void Parker::park(bool isAbsolute, jlong time) { ...@@ -4363,12 +4371,14 @@ void Parker::park(bool isAbsolute, jlong time) {
_counter = 0 ; _counter = 0 ;
status = pthread_mutex_unlock(_mutex) ; status = pthread_mutex_unlock(_mutex) ;
assert_status(status == 0, status, "invariant") ; assert_status(status == 0, status, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
// If externally suspended while waiting, re-suspend // If externally suspended while waiting, re-suspend
if (jt->handle_special_suspend_equivalent_condition()) { if (jt->handle_special_suspend_equivalent_condition()) {
jt->java_suspend_self(); jt->java_suspend_self();
} }
OrderAccess::fence();
} }
void Parker::unpark() { void Parker::unpark() {
......
/* /*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -5001,11 +5001,12 @@ void os::PlatformEvent::park() { // AKA "down()" ...@@ -5001,11 +5001,12 @@ void os::PlatformEvent::park() { // AKA "down()"
} }
-- _nParked ; -- _nParked ;
// In theory we could move the ST of 0 into _Event past the unlock(),
// but then we'd need a MEMBAR after the ST.
_Event = 0 ; _Event = 0 ;
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
} }
guarantee (_Event >= 0, "invariant") ; guarantee (_Event >= 0, "invariant") ;
} }
...@@ -5068,33 +5069,38 @@ int os::PlatformEvent::park(jlong millis) { ...@@ -5068,33 +5069,38 @@ int os::PlatformEvent::park(jlong millis) {
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
assert (_nParked == 0, "invariant") ; assert (_nParked == 0, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
return ret; return ret;
} }
void os::PlatformEvent::unpark() { void os::PlatformEvent::unpark() {
int v, AnyWaiters ; // Transitions for _Event:
for (;;) { // 0 :=> 1
v = _Event ; // 1 :=> 1
if (v > 0) { // -1 :=> either 0 or 1; must signal target thread
// The LD of _Event could have reordered or be satisfied // That is, we can safely transition _Event from -1 to either
// by a read-aside from this processor's write buffer. // 0 or 1. Forcing 1 is slightly more efficient for back-to-back
// To avoid problems execute a barrier and then // unpark() calls.
// ratify the value. // See also: "Semaphores in Plan 9" by Mullender & Cox
OrderAccess::fence() ; //
if (_Event == v) return ; // Note: Forcing a transition from "-1" to "1" on an unpark() means
continue ; // 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
if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; // from the first park() call after an unpark() call which will help
} // shake out uses of park() and unpark() without condition variables.
if (v < 0) {
if (Atomic::xchg(1, &_Event) >= 0) return;
// Wait for the thread associated with the event to vacate // Wait for the thread associated with the event to vacate
int status = pthread_mutex_lock(_mutex); int status = pthread_mutex_lock(_mutex);
assert_status(status == 0, status, "mutex_lock"); assert_status(status == 0, status, "mutex_lock");
AnyWaiters = _nParked ; int AnyWaiters = _nParked;
assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
AnyWaiters = 0 ; AnyWaiters = 0;
pthread_cond_signal (_cond); pthread_cond_signal(_cond);
} }
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
...@@ -5102,7 +5108,6 @@ void os::PlatformEvent::unpark() { ...@@ -5102,7 +5108,6 @@ void os::PlatformEvent::unpark() {
status = pthread_cond_signal(_cond); status = pthread_cond_signal(_cond);
assert_status(status == 0, status, "cond_signal"); assert_status(status == 0, status, "cond_signal");
} }
}
// Note that we signal() _after dropping the lock for "immortal" Events. // Note that we signal() _after dropping the lock for "immortal" Events.
// This is safe and avoids a common class of futile wakeups. In rare // This is safe and avoids a common class of futile wakeups. In rare
...@@ -5187,13 +5192,14 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { ...@@ -5187,13 +5192,14 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
} }
void Parker::park(bool isAbsolute, jlong time) { void Parker::park(bool isAbsolute, jlong time) {
// Ideally we'd do something useful while spinning, such
// as calling unpackTime().
// Optional fast-path check: // Optional fast-path check:
// Return immediately if a permit is available. // Return immediately if a permit is available.
if (_counter > 0) { // We depend on Atomic::xchg() having full barrier semantics
_counter = 0 ; // since we are doing a lock-free update to _counter.
OrderAccess::fence(); if (Atomic::xchg(0, &_counter) > 0) return;
return ;
}
Thread* thread = Thread::current(); Thread* thread = Thread::current();
assert(thread->is_Java_thread(), "Must be JavaThread"); assert(thread->is_Java_thread(), "Must be JavaThread");
...@@ -5234,6 +5240,8 @@ void Parker::park(bool isAbsolute, jlong time) { ...@@ -5234,6 +5240,8 @@ void Parker::park(bool isAbsolute, jlong time) {
_counter = 0; _counter = 0;
status = pthread_mutex_unlock(_mutex); status = pthread_mutex_unlock(_mutex);
assert (status == 0, "invariant") ; assert (status == 0, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence(); OrderAccess::fence();
return; return;
} }
...@@ -5270,12 +5278,14 @@ void Parker::park(bool isAbsolute, jlong time) { ...@@ -5270,12 +5278,14 @@ void Parker::park(bool isAbsolute, jlong time) {
_counter = 0 ; _counter = 0 ;
status = pthread_mutex_unlock(_mutex) ; status = pthread_mutex_unlock(_mutex) ;
assert_status(status == 0, status, "invariant") ; assert_status(status == 0, status, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
// If externally suspended while waiting, re-suspend // If externally suspended while waiting, re-suspend
if (jt->handle_special_suspend_equivalent_condition()) { if (jt->handle_special_suspend_equivalent_condition()) {
jt->java_suspend_self(); jt->java_suspend_self();
} }
OrderAccess::fence();
} }
void Parker::unpark() { void Parker::unpark() {
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -6014,6 +6014,9 @@ void os::PlatformEvent::park() { // AKA: down() ...@@ -6014,6 +6014,9 @@ void os::PlatformEvent::park() { // AKA: down()
_Event = 0 ; _Event = 0 ;
status = os::Solaris::mutex_unlock(_mutex); status = os::Solaris::mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
} }
} }
...@@ -6055,52 +6058,44 @@ int os::PlatformEvent::park(jlong millis) { ...@@ -6055,52 +6058,44 @@ int os::PlatformEvent::park(jlong millis) {
_Event = 0 ; _Event = 0 ;
status = os::Solaris::mutex_unlock(_mutex); status = os::Solaris::mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
return ret; return ret;
} }
void os::PlatformEvent::unpark() { void os::PlatformEvent::unpark() {
int v, AnyWaiters; // Transitions for _Event:
// 0 :=> 1
// Increment _Event. // 1 :=> 1
// Another acceptable implementation would be to simply swap 1 // -1 :=> either 0 or 1; must signal target thread
// into _Event: // That is, we can safely transition _Event from -1 to either
// if (Swap (&_Event, 1) < 0) { // 0 or 1. Forcing 1 is slightly more efficient for back-to-back
// mutex_lock (_mutex) ; AnyWaiters = nParked; mutex_unlock (_mutex) ; // unpark() calls.
// if (AnyWaiters) cond_signal (_cond) ; // 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.
for (;;) { if (Atomic::xchg(1, &_Event) >= 0) return;
v = _Event ;
if (v > 0) {
// 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 the thread associated with the event was parked, wake it. // If the thread associated with the event was parked, wake it.
if (v < 0) {
int status ;
// Wait for the thread assoc with the PlatformEvent to vacate. // Wait for the thread assoc with the PlatformEvent to vacate.
status = os::Solaris::mutex_lock(_mutex); int status = os::Solaris::mutex_lock(_mutex);
assert_status(status == 0, status, "mutex_lock"); assert_status(status == 0, status, "mutex_lock");
AnyWaiters = _nParked ; int AnyWaiters = _nParked;
status = os::Solaris::mutex_unlock(_mutex); status = os::Solaris::mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock"); assert_status(status == 0, status, "mutex_unlock");
guarantee (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
if (AnyWaiters != 0) { if (AnyWaiters != 0) {
// We intentional signal *after* dropping the lock // We intentional signal *after* dropping the lock
// to avoid a common class of futile wakeups. // to avoid a common class of futile wakeups.
status = os::Solaris::cond_signal(_cond); status = os::Solaris::cond_signal(_cond);
assert_status(status == 0, status, "cond_signal"); assert_status(status == 0, status, "cond_signal");
} }
}
} }
// JSR166 // JSR166
...@@ -6177,14 +6172,14 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { ...@@ -6177,14 +6172,14 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
} }
void Parker::park(bool isAbsolute, jlong time) { void Parker::park(bool isAbsolute, jlong time) {
// Ideally we'd do something useful while spinning, such
// as calling unpackTime().
// Optional fast-path check: // Optional fast-path check:
// Return immediately if a permit is available. // Return immediately if a permit is available.
if (_counter > 0) { // We depend on Atomic::xchg() having full barrier semantics
_counter = 0 ; // since we are doing a lock-free update to _counter.
OrderAccess::fence(); if (Atomic::xchg(0, &_counter) > 0) return;
return ;
}
// Optional fast-exit: Check interrupt before trying to wait // Optional fast-exit: Check interrupt before trying to wait
Thread* thread = Thread::current(); Thread* thread = Thread::current();
...@@ -6226,6 +6221,8 @@ void Parker::park(bool isAbsolute, jlong time) { ...@@ -6226,6 +6221,8 @@ void Parker::park(bool isAbsolute, jlong time) {
_counter = 0; _counter = 0;
status = os::Solaris::mutex_unlock(_mutex); status = os::Solaris::mutex_unlock(_mutex);
assert (status == 0, "invariant") ; assert (status == 0, "invariant") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence(); OrderAccess::fence();
return; return;
} }
...@@ -6267,12 +6264,14 @@ void Parker::park(bool isAbsolute, jlong time) { ...@@ -6267,12 +6264,14 @@ void Parker::park(bool isAbsolute, jlong time) {
_counter = 0 ; _counter = 0 ;
status = os::Solaris::mutex_unlock(_mutex); status = os::Solaris::mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock") ; assert_status(status == 0, status, "mutex_unlock") ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
// If externally suspended while waiting, re-suspend // If externally suspended while waiting, re-suspend
if (jt->handle_special_suspend_equivalent_condition()) { if (jt->handle_special_suspend_equivalent_condition()) {
jt->java_suspend_self(); jt->java_suspend_self();
} }
OrderAccess::fence();
} }
void Parker::unpark() { void Parker::unpark() {
......
...@@ -4565,6 +4565,7 @@ int os::PlatformEvent::park (jlong Millis) { ...@@ -4565,6 +4565,7 @@ int os::PlatformEvent::park (jlong Millis) {
} }
v = _Event ; v = _Event ;
_Event = 0 ; _Event = 0 ;
// see comment at end of os::PlatformEvent::park() below:
OrderAccess::fence() ; OrderAccess::fence() ;
// If we encounter a nearly simultanous timeout expiry and unpark() // If we encounter a nearly simultanous timeout expiry and unpark()
// we return OS_OK indicating we awoke via unpark(). // we return OS_OK indicating we awoke via unpark().
...@@ -4602,25 +4603,25 @@ void os::PlatformEvent::park () { ...@@ -4602,25 +4603,25 @@ void os::PlatformEvent::park () {
void os::PlatformEvent::unpark() { void os::PlatformEvent::unpark() {
guarantee (_ParkHandle != NULL, "Invariant") ; guarantee (_ParkHandle != NULL, "Invariant") ;
int v ;
for (;;) { // Transitions for _Event:
v = _Event ; // Increment _Event if it's < 1. // 0 :=> 1
if (v > 0) { // 1 :=> 1
// If it's already signaled just return. // -1 :=> either 0 or 1; must signal target thread
// The LD of _Event could have reordered or be satisfied // That is, we can safely transition _Event from -1 to either
// by a read-aside from this processor's write buffer. // 0 or 1. Forcing 1 is slightly more efficient for back-to-back
// To avoid problems execute a barrier and then // unpark() calls.
// ratify the value. A degenerate CAS() would also work. // See also: "Semaphores in Plan 9" by Mullender & Cox
// Viz., CAS (v+0, &_Event, v) == v). //
OrderAccess::fence() ; // Note: Forcing a transition from "-1" to "1" on an unpark() means
if (_Event == v) return ; // that it will take two back-to-back park() calls for the owning
continue ; // thread to block. This has the benefit of forcing a spurious return
} // from the first park() call after an unpark() call which will help
if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; // shake out uses of park() and unpark() without condition variables.
}
if (v < 0) { if (Atomic::xchg(1, &_Event) >= 0) return;
::SetEvent (_ParkHandle) ;
} ::SetEvent(_ParkHandle);
} }
......
...@@ -911,7 +911,6 @@ jlong java_lang_Thread::stackSize(oop java_thread) { ...@@ -911,7 +911,6 @@ jlong java_lang_Thread::stackSize(oop java_thread) {
// Write the thread status value to threadStatus field in java.lang.Thread java class. // Write the thread status value to threadStatus field in java.lang.Thread java class.
void java_lang_Thread::set_thread_status(oop java_thread, void java_lang_Thread::set_thread_status(oop java_thread,
java_lang_Thread::ThreadStatus status) { java_lang_Thread::ThreadStatus status) {
assert(JavaThread::current()->thread_state() == _thread_in_vm, "Java Thread is not running in vm");
// The threadStatus is only present starting in 1.5 // The threadStatus is only present starting in 1.5
if (_thread_status_offset > 0) { if (_thread_status_offset > 0) {
java_thread->int_field_put(_thread_status_offset, status); java_thread->int_field_put(_thread_status_offset, status);
......
/* /*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -653,8 +653,7 @@ void ATTR ObjectMonitor::EnterI (TRAPS) { ...@@ -653,8 +653,7 @@ void ATTR ObjectMonitor::EnterI (TRAPS) {
assert (_succ != Self, "invariant") ; assert (_succ != Self, "invariant") ;
if (_Responsible == Self) { if (_Responsible == Self) {
_Responsible = NULL ; _Responsible = NULL ;
// Dekker pivot-point. OrderAccess::fence(); // Dekker pivot-point
// Consider OrderAccess::storeload() here
// We may leave threads on cxq|EntryList without a designated // We may leave threads on cxq|EntryList without a designated
// "Responsible" thread. This is benign. When this thread subsequently // "Responsible" thread. This is benign. When this thread subsequently
...@@ -674,10 +673,6 @@ void ATTR ObjectMonitor::EnterI (TRAPS) { ...@@ -674,10 +673,6 @@ void ATTR ObjectMonitor::EnterI (TRAPS) {
// //
// The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent
// exit operation from floating above the ST Responsible=null. // exit operation from floating above the ST Responsible=null.
//
// In *practice* however, EnterI() is always followed by some atomic
// operation such as the decrement of _count in ::enter(). Those atomics
// obviate the need for the explicit MEMBAR, above.
} }
// We've acquired ownership with CAS(). // We've acquired ownership with CAS().
......
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -101,10 +101,12 @@ inline intptr_t ObjectMonitor::contentions() const { ...@@ -101,10 +101,12 @@ inline intptr_t ObjectMonitor::contentions() const {
return _count; return _count;
} }
// Do NOT set _count = 0. There is a race such that _count could
// be set while inflating prior to setting _owner
// Just use Atomic::inc/dec and assert 0 when monitor put on free list
inline void ObjectMonitor::set_owner(void* owner) { inline void ObjectMonitor::set_owner(void* owner) {
_owner = owner; _owner = owner;
_recursions = 0; _recursions = 0;
_count = 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册