< prev index next >
src/hotspot/share/runtime/objectMonitor.cpp
Print this page
rev 57232 : v2.00 -> v2.08 (CR8/v2.08/11-for-jdk14) patches combined into one; merge with jdk-14+25 snapshot; merge with jdk-14+26 snapshot.
rev 57233 : See CR8-to-CR9-changes; merge with 8230876.patch (2019.11.15); merge with jdk-14+25 snapshot; fuzzy merge with jdk-14+26 snapshot.
*** 304,318 ****
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(jt->thread_state() != _thread_blocked, "invariant");
assert(this->object() != NULL, "invariant");
assert(_contentions >= 0, "must not be negative: contentions=%d", _contentions);
! // Prevent deflation. See ObjectSynchronizer::deflate_monitor(),
! // ObjectSynchronizer::deflate_monitor_using_JT() and is_busy().
! // Ensure the object <-> monitor relationship remains stable while
! // there's contention.
! Atomic::add(&_contentions, 1);
JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
EventJavaMonitorEnter event;
if (event.should_commit()) {
event.set_monitorClass(((oop)this->object())->klass());
--- 304,315 ----
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(jt->thread_state() != _thread_blocked, "invariant");
assert(this->object() != NULL, "invariant");
assert(_contentions >= 0, "must not be negative: contentions=%d", _contentions);
! // Keep track of contention for JVM/TI and M&M queries.
! Atomic::inc(&_contentions);
JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
EventJavaMonitorEnter event;
if (event.should_commit()) {
event.set_monitorClass(((oop)this->object())->klass());
*** 946,957 ****
// inopportune) reclamation of "this".
//
// We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
// There's one exception to the claim above, however. EnterI() can call
// exit() to drop a lock if the acquirer has been externally suspended.
! // In that case exit() is called with _thread_state as _thread_blocked,
! // but the monitor's _contentions field is > 0, which inhibits reclamation.
//
// 1-0 exit
// ~~~~~~~~
// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
// the fast-path operators have been optimized so the common ::exit()
--- 943,954 ----
// inopportune) reclamation of "this".
//
// We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
// There's one exception to the claim above, however. EnterI() can call
// exit() to drop a lock if the acquirer has been externally suspended.
! // In that case exit() is called with _thread_state == _thread_blocked,
! // but the monitor's ref_count is > 0, which inhibits reclamation.
//
// 1-0 exit
// ~~~~~~~~
// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
// the fast-path operators have been optimized so the common ::exit()
*** 1007,1026 ****
// see x86_32.ad Fast_Unlock() and the I1 and I2 properties.
// Upon deeper reflection, however, in a properly run JVM the only
// way we should encounter this situation is in the presence of
// unbalanced JNI locking. TODO: CheckJNICalls.
// See also: CR4414101
! //#ifdef ASSERT
LogStreamHandle(Error, monitorinflation) lsh;
lsh.print_cr("ERROR: ObjectMonitor::exit(): thread=" INTPTR_FORMAT
" is exiting an ObjectMonitor it does not own.", p2i(THREAD));
lsh.print_cr("The imbalance is possibly caused by JNI locking.");
print_debug_style_on(&lsh);
! //#endif
! // Changing this from an assert() to ADIM_guarantee() may run
! // afoul of any test that is inducing non-balanced JNI locking.
! ADIM_guarantee(false, "Non-balanced monitor enter/exit!");
return;
}
}
if (_recursions != 0) {
--- 1004,1021 ----
// see x86_32.ad Fast_Unlock() and the I1 and I2 properties.
// Upon deeper reflection, however, in a properly run JVM the only
// way we should encounter this situation is in the presence of
// unbalanced JNI locking. TODO: CheckJNICalls.
// See also: CR4414101
! #ifdef ASSERT
LogStreamHandle(Error, monitorinflation) lsh;
lsh.print_cr("ERROR: ObjectMonitor::exit(): thread=" INTPTR_FORMAT
" is exiting an ObjectMonitor it does not own.", p2i(THREAD));
lsh.print_cr("The imbalance is possibly caused by JNI locking.");
print_debug_style_on(&lsh);
! #endif
! assert(false, "Non-balanced monitor enter/exit!");
return;
}
}
if (_recursions != 0) {
*** 1041,1058 ****
#endif
for (;;) {
assert(THREAD == _owner, "invariant");
// release semantics: prior loads and stores from within the critical section
// must not float (reorder) past the following store that drops the lock.
! if (AsyncDeflateIdleMonitors) {
! set_owner_from(NULL, Self);
! } else {
! Atomic::release_store(&_owner, (void*)NULL); // drop the lock
! OrderAccess::storeload(); // See if we need to wake a successor
! }
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
return;
}
// Other threads are blocked trying to acquire the lock.
--- 1036,1053 ----
#endif
for (;;) {
assert(THREAD == _owner, "invariant");
+ // Drop the lock.
// release semantics: prior loads and stores from within the critical section
// must not float (reorder) past the following store that drops the lock.
! // Uses a storeload to separate release_store(owner) from the
! // successor check. The try_set_owner() below uses cmpxchg() so
! // we get the fence down there.
! release_clear_owner_with_barrier(Self, /* needs_fence */ false);
!
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
return;
}
// Other threads are blocked trying to acquire the lock.
*** 1222,1238 ****
// Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
// The thread associated with Wakee may have grabbed the lock and "Wakee" may be
// out-of-scope (non-extant).
Wakee = NULL;
! // Drop the lock
! if (AsyncDeflateIdleMonitors) {
! set_owner_from(NULL, Self);
! } else {
! Atomic::release_store(&_owner, (void*)NULL);
! OrderAccess::fence(); // ST _owner vs LD in unpark()
! }
DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
Trigger->unpark();
// Maintain stats and report events to JVMTI
--- 1217,1229 ----
// Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
// The thread associated with Wakee may have grabbed the lock and "Wakee" may be
// out-of-scope (non-extant).
Wakee = NULL;
! // Drop the lock.
! // Uses a fence to separate release_store(owner) from the LD in unpark().
! release_clear_owner_with_barrier(Self, /* needs_fence */ true);
DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
Trigger->unpark();
// Maintain stats and report events to JVMTI
*** 2099,2110 ****
// This function returns true if the ObjectMonitor* has been safely
// saved. This function returns false if we have lost a race with
// async deflation; the caller should retry as appropriate.
//
bool ObjectMonitorHandle::save_om_ptr(oop object, markWord mark) {
! guarantee(mark.has_monitor(), "sanity check: mark=" INTPTR_FORMAT,
! mark.value());
ObjectMonitor* om_ptr = mark.monitor();
om_ptr->inc_ref_count();
if (AsyncDeflateIdleMonitors) {
--- 2090,2103 ----
// This function returns true if the ObjectMonitor* has been safely
// saved. This function returns false if we have lost a race with
// async deflation; the caller should retry as appropriate.
//
bool ObjectMonitorHandle::save_om_ptr(oop object, markWord mark) {
! // is_marked() is a superset of has_monitor() so make sure we
! // are called with the proper markWord value.
! guarantee(mark.has_monitor() && !mark.is_marked(), "sanity check: mark="
! INTPTR_FORMAT, mark.value());
ObjectMonitor* om_ptr = mark.monitor();
om_ptr->inc_ref_count();
if (AsyncDeflateIdleMonitors) {
*** 2213,2223 ****
contentions(), waiters(), recursions(),
p2i(owner()));
}
void ObjectMonitor::print() const { print_on(tty); }
! //#ifdef ASSERT
// Print the ObjectMonitor like a debugger would:
//
// (ObjectMonitor) 0x00007fdfb6012e40 = {
// _header = 0x0000000000000001
// _object = 0x000000070ff45fd0
--- 2206,2216 ----
contentions(), waiters(), recursions(),
p2i(owner()));
}
void ObjectMonitor::print() const { print_on(tty); }
! #ifdef ASSERT
// Print the ObjectMonitor like a debugger would:
//
// (ObjectMonitor) 0x00007fdfb6012e40 = {
// _header = 0x0000000000000001
// _object = 0x000000070ff45fd0
*** 2285,2295 ****
st->print_cr(" _pad_buf2 = {");
st->print_cr(" [0] = '\\0'");
st->print_cr(" ...");
st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf1) - 1);
st->print_cr(" }");
! st->print_cr(" _next_om = " INTPTR_FORMAT, p2i(_next_om));
st->print_cr(" _recursions = " INTX_FORMAT, _recursions);
st->print_cr(" _EntryList = " INTPTR_FORMAT, p2i(_EntryList));
st->print_cr(" _cxq = " INTPTR_FORMAT, p2i(_cxq));
st->print_cr(" _succ = " INTPTR_FORMAT, p2i(_succ));
st->print_cr(" _Responsible = " INTPTR_FORMAT, p2i(_Responsible));
--- 2278,2288 ----
st->print_cr(" _pad_buf2 = {");
st->print_cr(" [0] = '\\0'");
st->print_cr(" ...");
st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf1) - 1);
st->print_cr(" }");
! st->print_cr(" _next_om = " INTPTR_FORMAT, p2i(Atomic::load(&_next_om)));
st->print_cr(" _recursions = " INTX_FORMAT, _recursions);
st->print_cr(" _EntryList = " INTPTR_FORMAT, p2i(_EntryList));
st->print_cr(" _cxq = " INTPTR_FORMAT, p2i(_cxq));
st->print_cr(" _succ = " INTPTR_FORMAT, p2i(_succ));
st->print_cr(" _Responsible = " INTPTR_FORMAT, p2i(_Responsible));
*** 2299,2304 ****
st->print_cr(" _WaitSet = " INTPTR_FORMAT, p2i(_WaitSet));
st->print_cr(" _waiters = %d", _waiters);
st->print_cr(" _WaitSetLock = %d", _WaitSetLock);
st->print_cr("}");
}
! //#endif
--- 2292,2297 ----
st->print_cr(" _WaitSet = " INTPTR_FORMAT, p2i(_WaitSet));
st->print_cr(" _waiters = %d", _waiters);
st->print_cr(" _WaitSetLock = %d", _WaitSetLock);
st->print_cr("}");
}
! #endif
< prev index next >