8320317: ObjectMonitor NotRunnable is not really an optimization

Reviewed-by: eosterlund, dholmes, shade, dcubed
This commit is contained in:
Fredrik Bredberg 2024-01-08 13:32:17 +00:00 committed by Erik Österlund
parent fc04750817
commit 29397d29ba
2 changed files with 0 additions and 68 deletions
src/hotspot/share/runtime

@ -1844,10 +1844,6 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
ctr = _SpinDuration;
if (ctr <= 0) return 0;
if (NotRunnable(current, static_cast<JavaThread*>(owner_raw()))) {
return 0;
}
// We're good to spin ... spin ingress.
// CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades
// when preparing to LD...CAS _owner, etc and the CAS is likely
@ -1933,13 +1929,6 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
}
prv = ox;
// Abort the spin if the owner is not executing.
// The owner must be executing in order to drop the lock.
// Spinning while the owner is OFFPROC is idiocy.
// Consider: ctr -= RunnablePenalty ;
if (NotRunnable(current, ox)) {
goto Abort;
}
if (_succ == nullptr) {
_succ = current;
}
@ -1972,62 +1961,6 @@ int ObjectMonitor::TrySpin(JavaThread* current) {
return 0;
}
// NotRunnable() -- informed spinning
//
// Don't bother spinning if the owner is not eligible to drop the lock.
// Spin only if the owner thread is _thread_in_Java or _thread_in_vm.
// The thread must be runnable in order to drop the lock in timely fashion.
// If the _owner is not runnable then spinning will not likely be
// successful (profitable).
//
// Beware -- the thread referenced by _owner could have died
// so a simply fetch from _owner->_thread_state might trap.
// Instead, we use SafeFetchXX() to safely LD _owner->_thread_state.
// Because of the lifecycle issues, the _thread_state values
// observed by NotRunnable() might be garbage. NotRunnable must
// tolerate this and consider the observed _thread_state value
// as advisory.
//
// Beware too, that _owner is sometimes a BasicLock address and sometimes
// a thread pointer.
// Alternately, we might tag the type (thread pointer vs basiclock pointer)
// with the LSB of _owner. Another option would be to probabilistically probe
// the putative _owner->TypeTag value.
//
// Checking _thread_state isn't perfect. Even if the thread is
// in_java it might be blocked on a page-fault or have been preempted
// and sitting on a ready/dispatch queue.
//
// The return value from NotRunnable() is *advisory* -- the
// result is based on sampling and is not necessarily coherent.
// The caller must tolerate false-negative and false-positive errors.
// Spinning, in general, is probabilistic anyway.
int ObjectMonitor::NotRunnable(JavaThread* current, JavaThread* ox) {
// Check ox->TypeTag == 2BAD.
if (ox == nullptr) return 0;
// Avoid transitive spinning ...
// Say T1 spins or blocks trying to acquire L. T1._Stalled is set to L.
// Immediately after T1 acquires L it's possible that T2, also
// spinning on L, will see L.Owner=T1 and T1._Stalled=L.
// This occurs transiently after T1 acquired L but before
// T1 managed to clear T1.Stalled. T2 does not need to abort
// its spin in this circumstance.
intptr_t BlockedOn = SafeFetchN((intptr_t *) &ox->_Stalled, intptr_t(1));
if (BlockedOn == 1) return 1;
if (BlockedOn != 0) {
return BlockedOn != intptr_t(this) && owner_raw() == ox;
}
assert(sizeof(ox->_thread_state == sizeof(int)), "invariant");
int jst = SafeFetch32((int *) &ox->_thread_state, -1);;
// consider also: jst != _thread_in_Java -- but that's overspecific.
return jst == _thread_blocked || jst == _thread_in_native;
}
// -----------------------------------------------------------------------------
// WaitSet management ...

@ -353,7 +353,6 @@ private:
void ReenterI(JavaThread* current, ObjectWaiter* current_node);
void UnlinkAfterAcquire(JavaThread* current, ObjectWaiter* current_node);
int TryLock(JavaThread* current);
int NotRunnable(JavaThread* current, JavaThread* Owner);
int TrySpin(JavaThread* current);
void ExitEpilog(JavaThread* current, ObjectWaiter* Wakee);