mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
8004902: correctness fixes motivated by contended locking work (6607129)
Misc correctness fixes Reviewed-by: acorn, dholmes, dice, sspitsyn
This commit is contained in:
parent
8f1dc20874
commit
98c357abf8
7 changed files with 168 additions and 152 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -5001,11 +5001,12 @@ void os::PlatformEvent::park() { // AKA "down()"
|
|||
}
|
||||
-- _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 ;
|
||||
status = pthread_mutex_unlock(_mutex);
|
||||
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") ;
|
||||
}
|
||||
|
@ -5068,40 +5069,44 @@ int os::PlatformEvent::park(jlong millis) {
|
|||
status = pthread_mutex_unlock(_mutex);
|
||||
assert_status(status == 0, status, "mutex_unlock");
|
||||
assert (_nParked == 0, "invariant") ;
|
||||
// Paranoia to ensure our locked and lock-free paths interact
|
||||
// correctly with each other.
|
||||
OrderAccess::fence();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void os::PlatformEvent::unpark() {
|
||||
int v, AnyWaiters ;
|
||||
for (;;) {
|
||||
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.
|
||||
OrderAccess::fence() ;
|
||||
if (_Event == v) return ;
|
||||
continue ;
|
||||
}
|
||||
if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ;
|
||||
// Transitions for _Event:
|
||||
// 0 :=> 1
|
||||
// 1 :=> 1
|
||||
// -1 :=> either 0 or 1; must signal target thread
|
||||
// That is, we can safely transition _Event from -1 to either
|
||||
// 0 or 1. Forcing 1 is slightly more efficient for back-to-back
|
||||
// unpark() calls.
|
||||
// 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.
|
||||
|
||||
if (Atomic::xchg(1, &_Event) >= 0) return;
|
||||
|
||||
// Wait for the thread associated with the event to vacate
|
||||
int status = pthread_mutex_lock(_mutex);
|
||||
assert_status(status == 0, status, "mutex_lock");
|
||||
int AnyWaiters = _nParked;
|
||||
assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
|
||||
if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
|
||||
AnyWaiters = 0;
|
||||
pthread_cond_signal(_cond);
|
||||
}
|
||||
if (v < 0) {
|
||||
// Wait for the thread associated with the event to vacate
|
||||
int status = pthread_mutex_lock(_mutex);
|
||||
assert_status(status == 0, status, "mutex_lock");
|
||||
AnyWaiters = _nParked ;
|
||||
assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ;
|
||||
if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
|
||||
AnyWaiters = 0 ;
|
||||
pthread_cond_signal (_cond);
|
||||
}
|
||||
status = pthread_mutex_unlock(_mutex);
|
||||
assert_status(status == 0, status, "mutex_unlock");
|
||||
if (AnyWaiters != 0) {
|
||||
status = pthread_cond_signal(_cond);
|
||||
assert_status(status == 0, status, "cond_signal");
|
||||
}
|
||||
status = pthread_mutex_unlock(_mutex);
|
||||
assert_status(status == 0, status, "mutex_unlock");
|
||||
if (AnyWaiters != 0) {
|
||||
status = pthread_cond_signal(_cond);
|
||||
assert_status(status == 0, status, "cond_signal");
|
||||
}
|
||||
|
||||
// Note that we signal() _after dropping the lock for "immortal" Events.
|
||||
|
@ -5187,13 +5192,14 @@ static void unpackTime(timespec* absTime, 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:
|
||||
// Return immediately if a permit is available.
|
||||
if (_counter > 0) {
|
||||
_counter = 0 ;
|
||||
OrderAccess::fence();
|
||||
return ;
|
||||
}
|
||||
// We depend on Atomic::xchg() having full barrier semantics
|
||||
// since we are doing a lock-free update to _counter.
|
||||
if (Atomic::xchg(0, &_counter) > 0) return;
|
||||
|
||||
Thread* thread = Thread::current();
|
||||
assert(thread->is_Java_thread(), "Must be JavaThread");
|
||||
|
@ -5234,6 +5240,8 @@ void Parker::park(bool isAbsolute, jlong time) {
|
|||
_counter = 0;
|
||||
status = pthread_mutex_unlock(_mutex);
|
||||
assert (status == 0, "invariant") ;
|
||||
// Paranoia to ensure our locked and lock-free paths interact
|
||||
// correctly with each other and Java-level accesses.
|
||||
OrderAccess::fence();
|
||||
return;
|
||||
}
|
||||
|
@ -5270,12 +5278,14 @@ void Parker::park(bool isAbsolute, jlong time) {
|
|||
_counter = 0 ;
|
||||
status = pthread_mutex_unlock(_mutex) ;
|
||||
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 (jt->handle_special_suspend_equivalent_condition()) {
|
||||
jt->java_suspend_self();
|
||||
}
|
||||
|
||||
OrderAccess::fence();
|
||||
}
|
||||
|
||||
void Parker::unpark() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue