mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8075171: Contended Locking fast notify bucket
JEP-143/JDK-8073165 Contended Locking fast notify bucket Co-authored-by: Dave Dice <dave.dice@oracle.com> Co-authored-by: Karen Kinnear <karen.kinnear@oracle.com> Reviewed-by: dholmes, acorn, dice, dcubed
This commit is contained in:
parent
a692c78dfc
commit
d7f565d9eb
10 changed files with 242 additions and 169 deletions
|
@ -86,6 +86,8 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
|||
} \
|
||||
}
|
||||
|
||||
#define HOTSPOT_MONITOR_PROBE_notify HOTSPOT_MONITOR_NOTIFY
|
||||
#define HOTSPOT_MONITOR_PROBE_notifyAll HOTSPOT_MONITOR_NOTIFYALL
|
||||
#define HOTSPOT_MONITOR_PROBE_waited HOTSPOT_MONITOR_WAITED
|
||||
|
||||
#define DTRACE_MONITOR_PROBE(probe, monitor, obj, thread) \
|
||||
|
@ -146,6 +148,58 @@ static volatile int gMonitorPopulation = 0; // # Extant -- in circulation
|
|||
// operators: safepoints or indefinite blocking (blocking that might span a
|
||||
// safepoint) are forbidden. Generally the thread_state() is _in_Java upon
|
||||
// entry.
|
||||
//
|
||||
// Consider: An interesting optimization is to have the JIT recognize the
|
||||
// following common idiom:
|
||||
// synchronized (someobj) { .... ; notify(); }
|
||||
// That is, we find a notify() or notifyAll() call that immediately precedes
|
||||
// the monitorexit operation. In that case the JIT could fuse the operations
|
||||
// into a single notifyAndExit() runtime primitive.
|
||||
|
||||
bool ObjectSynchronizer::quick_notify(oopDesc * obj, Thread * self, bool all) {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
assert(self->is_Java_thread(), "invariant");
|
||||
assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
|
||||
No_Safepoint_Verifier nsv;
|
||||
if (obj == NULL) return false; // slow-path for invalid obj
|
||||
const markOop mark = obj->mark();
|
||||
|
||||
if (mark->has_locker() && self->is_lock_owned((address)mark->locker())) {
|
||||
// Degenerate notify
|
||||
// stack-locked by caller so by definition the implied waitset is empty.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mark->has_monitor()) {
|
||||
ObjectMonitor * const mon = mark->monitor();
|
||||
assert(mon->object() == obj, "invariant");
|
||||
if (mon->owner() != self) return false; // slow-path for IMS exception
|
||||
|
||||
if (mon->first_waiter() != NULL) {
|
||||
// We have one or more waiters. Since this is an inflated monitor
|
||||
// that we own, we can transfer one or more threads from the waitset
|
||||
// to the entrylist here and now, avoiding the slow-path.
|
||||
if (all) {
|
||||
DTRACE_MONITOR_PROBE(notifyAll, mon, obj, self);
|
||||
} else {
|
||||
DTRACE_MONITOR_PROBE(notify, mon, obj, self);
|
||||
}
|
||||
int tally = 0;
|
||||
do {
|
||||
mon->INotify(self);
|
||||
++tally;
|
||||
} while (mon->first_waiter() != NULL && all);
|
||||
if (ObjectMonitor::_sync_Notifications != NULL) {
|
||||
ObjectMonitor::_sync_Notifications->inc(tally);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// biased locking and any other IMS exception states take the slow-path
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The LockNode emitted directly at the synchronization site would have
|
||||
// been too big if it were to have included support for the cases of inflated
|
||||
|
@ -1451,8 +1505,7 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
|
|||
// This is an unfortunate aspect of this design.
|
||||
|
||||
enum ManifestConstants {
|
||||
ClearResponsibleAtSTW = 0,
|
||||
MaximumRecheckInterval = 1000
|
||||
ClearResponsibleAtSTW = 0
|
||||
};
|
||||
|
||||
// Deflate a single monitor if not in-use
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue