< prev index next >

src/hotspot/share/runtime/objectMonitor.cpp

Print this page
rev 54612 : Checkpoint latest preliminary review patches for full OpenJDK review; merge with 8222295.patch.
rev 54613 : imported patch dcubed.monitor_deflate_conc.v2.01
rev 54614 : imported patch dcubed.monitor_deflate_conc.v2.02
rev 54615 : imported patch dcubed.monitor_deflate_conc.v2.03

*** 236,271 **** } // ----------------------------------------------------------------------------- // Enter support ! bool ObjectMonitor::enter(TRAPS) { // The following code is ordered to check the most common cases first // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors. Thread * const Self = THREAD; void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL); if (cur == NULL) { // Either ASSERT _recursions == 0 or explicitly set _recursions = 0. assert(_recursions == 0, "invariant"); assert(_owner == Self, "invariant"); ! return true; } if (cur == Self) { // TODO-FIXME: check for integer overflow! BUGID 6557169. _recursions++; ! return true; } if (Self->is_lock_owned ((address)cur)) { assert(_recursions == 0, "internal state error"); _recursions = 1; // Commute owner from a thread-specific on-stack BasicLockObject address to // a full-fledged "Thread *". _owner = Self; ! return true; } // We've encountered genuine contention. assert(Self->_Stalled == 0, "invariant"); Self->_Stalled = intptr_t(this); --- 236,273 ---- } // ----------------------------------------------------------------------------- // Enter support ! void ObjectMonitor::enter(TRAPS) { ! ADIM_guarantee(_ref_count > 0, "must be positive: ref_count=%d", _ref_count); ! // The following code is ordered to check the most common cases first // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors. Thread * const Self = THREAD; void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL); if (cur == NULL) { // Either ASSERT _recursions == 0 or explicitly set _recursions = 0. assert(_recursions == 0, "invariant"); assert(_owner == Self, "invariant"); ! return; } if (cur == Self) { // TODO-FIXME: check for integer overflow! BUGID 6557169. _recursions++; ! return; } if (Self->is_lock_owned ((address)cur)) { assert(_recursions == 0, "internal state error"); _recursions = 1; // Commute owner from a thread-specific on-stack BasicLockObject address to // a full-fledged "Thread *". _owner = Self; ! return; } // We've encountered genuine contention. assert(Self->_Stalled == 0, "invariant"); Self->_Stalled = intptr_t(this);
*** 282,316 **** assert(((oop)object())->mark() == markOopDesc::encode(this), "object mark must match encoded this: mark=" INTPTR_FORMAT ", encoded this=" INTPTR_FORMAT, p2i(((oop)object())->mark()), p2i(markOopDesc::encode(this))); Self->_Stalled = 0; ! return true; } assert(_owner != Self, "invariant"); assert(_succ != Self, "invariant"); assert(Self->is_Java_thread(), "invariant"); JavaThread * jt = (JavaThread *) Self; assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(jt->thread_state() != _thread_blocked, "invariant"); assert(AsyncDeflateIdleMonitors || this->object() != NULL, "invariant"); ! assert(AsyncDeflateIdleMonitors || _contentions >= 0, "invariant"); ! // Prevent deflation. See ObjectSynchronizer::deflate_monitor() and is_busy(). ! // Ensure the object-monitor relationship remains stable while there's contention. ! const jint contentions = Atomic::add(1, &_contentions); ! if (contentions <= 0 && _owner == DEFLATER_MARKER) { ! // Async deflation is in progress. Attempt to restore the ! // header/dmw to the object's header so that we only retry once ! // if the deflater thread happens to be slow. ! const oop obj = (oop) object(); ! install_displaced_markword_in_object(obj); ! Self->_Stalled = 0; ! return false; // Caller should retry. Never mind about _contentions as this monitor has been deflated. ! } ! // The deflater thread will not deflate this monitor and the monitor is contended, continue. JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);) EventJavaMonitorEnter event; if (event.should_commit()) { event.set_monitorClass(((oop)this->object())->klass()); --- 284,310 ---- assert(((oop)object())->mark() == markOopDesc::encode(this), "object mark must match encoded this: mark=" INTPTR_FORMAT ", encoded this=" INTPTR_FORMAT, p2i(((oop)object())->mark()), p2i(markOopDesc::encode(this))); Self->_Stalled = 0; ! return; } assert(_owner != Self, "invariant"); assert(_succ != Self, "invariant"); assert(Self->is_Java_thread(), "invariant"); JavaThread * jt = (JavaThread *) Self; assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(jt->thread_state() != _thread_blocked, "invariant"); assert(AsyncDeflateIdleMonitors || 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(1, &_contentions); JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);) EventJavaMonitorEnter event; if (event.should_commit()) { event.set_monitorClass(((oop)this->object())->klass());
*** 368,378 **** // states will still report that the thread is blocked trying to // acquire it. } Atomic::dec(&_contentions); ! assert(AsyncDeflateIdleMonitors || _contentions >= 0, "invariant"); Self->_Stalled = 0; // Must either set _recursions = 0 or ASSERT _recursions == 0. assert(_recursions == 0, "invariant"); assert(_owner == Self, "invariant"); --- 362,372 ---- // states will still report that the thread is blocked trying to // acquire it. } Atomic::dec(&_contentions); ! assert(_contentions >= 0, "must not be negative: contentions=%d", _contentions); Self->_Stalled = 0; // Must either set _recursions = 0 or ASSERT _recursions == 0. assert(_recursions == 0, "invariant"); assert(_owner == Self, "invariant");
*** 404,414 **** if (event.should_commit()) { event.set_previousOwner((uintptr_t)_previous_owner_tid); event.commit(); } OM_PERFDATA_OP(ContendedLockAttempts, inc()); - return true; } // Caveat: TryLock() is not necessarily serializing if it returns failure. // Callers must compensate as needed. --- 398,407 ----
*** 433,443 **** // idempotent method is called by a thread that is deflating a // monitor and by other threads that have detected a race with the // deflation process. void ObjectMonitor::install_displaced_markword_in_object(const oop obj) { // This function must only be called when (owner == DEFLATER_MARKER ! // && contentions <= 0), but we can't guarantee that here because // those values could change when the ObjectMonitor gets moved from // the global free list to a per-thread free list. guarantee(obj != NULL, "must be non-NULL"); if (object() != obj) { --- 426,436 ---- // idempotent method is called by a thread that is deflating a // monitor and by other threads that have detected a race with the // deflation process. void ObjectMonitor::install_displaced_markword_in_object(const oop obj) { // This function must only be called when (owner == DEFLATER_MARKER ! // && ref_count <= 0), but we can't guarantee that here because // those values could change when the ObjectMonitor gets moved from // the global free list to a per-thread free list. guarantee(obj != NULL, "must be non-NULL"); if (object() != obj) {
*** 508,517 **** --- 501,512 ---- } #define MAX_RECHECK_INTERVAL 1000 void ObjectMonitor::EnterI(TRAPS) { + ADIM_guarantee(_ref_count > 0, "must be positive: ref_count=%d", _ref_count); + Thread * const Self = THREAD; assert(Self->is_Java_thread(), "invariant"); assert(((JavaThread *) Self)->thread_state() == _thread_blocked, "invariant"); // Try the lock - TATAS
*** 521,536 **** assert(_Responsible != Self, "invariant"); return; } if (_owner == DEFLATER_MARKER) { ! // The deflation protocol finished the first part (setting _owner), but ! // it failed the second part (making _contentions negative) and bailed. ! // Because we're called from enter() we have at least one contention. ! guarantee(_contentions > 0, "owner == DEFLATER_MARKER && contentions <= 0 " ! "should have been handled by the caller: contentions=%d", ! _contentions); if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { // Acquired the monitor. assert(_succ != Self, "invariant"); assert(_Responsible != Self, "invariant"); return; --- 516,527 ---- assert(_Responsible != Self, "invariant"); return; } if (_owner == DEFLATER_MARKER) { ! // The deflation protocol finished the first part (setting owner), but ! // it failed the second part (making ref_count negative) and bailed. if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { // Acquired the monitor. assert(_succ != Self, "invariant"); assert(_Responsible != Self, "invariant"); return;
*** 652,667 **** } if (TryLock(Self) > 0) break; if (_owner == DEFLATER_MARKER) { ! // The deflation protocol finished the first part (setting _owner), but ! // it failed the second part (making _contentions negative) and bailed. ! // Because we're called from enter() we have at least one contention. ! guarantee(_contentions > 0, "owner == DEFLATER_MARKER && contentions <= 0 " ! "should have been handled by the caller: contentions=%d", ! _contentions); if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { // Acquired the monitor. break; } } --- 643,654 ---- } if (TryLock(Self) > 0) break; if (_owner == DEFLATER_MARKER) { ! // The deflation protocol finished the first part (setting owner), but ! // it failed the second part (making ref_count negative) and bailed. if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { // Acquired the monitor. break; } }
*** 768,777 **** --- 755,766 ---- // monitor reentry in wait(). // // In the future we should reconcile EnterI() and ReenterI(). void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) { + ADIM_guarantee(_ref_count > 0, "must be positive: ref_count=%d", _ref_count); + assert(Self != NULL, "invariant"); assert(SelfNode != NULL, "invariant"); assert(SelfNode->_thread == Self, "invariant"); assert(_waiters > 0, "invariant"); assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
*** 786,801 **** if (TryLock(Self) > 0) break; if (TrySpin(Self) > 0) break; if (_owner == DEFLATER_MARKER) { ! // The deflation protocol finished the first part (setting _owner), ! // but it will observe _waiters != 0 and will bail out. Because we're ! // called from wait() we may or may not have any contentions. ! guarantee(_contentions >= 0, "owner == DEFLATER_MARKER && contentions < 0 " ! "should have been handled by the caller: contentions=%d", ! _contentions); if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { // Acquired the monitor. break; } } --- 775,786 ---- if (TryLock(Self) > 0) break; if (TrySpin(Self) > 0) break; if (_owner == DEFLATER_MARKER) { ! // The deflation protocol finished the first part (setting owner), but ! // it failed the second part (making ref_count negative) and bailed. if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { // Acquired the monitor. break; } }
*** 1256,1279 **** return save; } // reenter() enters a lock and sets recursion count // complete_exit/reenter operate as a wait without waiting ! bool ObjectMonitor::reenter(intptr_t recursions, TRAPS) { Thread * const Self = THREAD; assert(Self->is_Java_thread(), "Must be Java thread!"); JavaThread *jt = (JavaThread *)THREAD; guarantee(_owner != Self, "reenter already owner"); ! if (!enter(THREAD)) { ! // Failed to enter the monitor so return for a retry. ! return false; ! } // Entered the monitor. guarantee(_recursions == 0, "reenter recursion"); _recursions = recursions; - return true; } // ----------------------------------------------------------------------------- // A macro is used below because there may already be a pending --- 1241,1260 ---- return save; } // reenter() enters a lock and sets recursion count // complete_exit/reenter operate as a wait without waiting ! void ObjectMonitor::reenter(intptr_t recursions, TRAPS) { Thread * const Self = THREAD; assert(Self->is_Java_thread(), "Must be Java thread!"); JavaThread *jt = (JavaThread *)THREAD; guarantee(_owner != Self, "reenter already owner"); ! enter(THREAD); // Entered the monitor. guarantee(_recursions == 0, "reenter recursion"); _recursions = recursions; } // ----------------------------------------------------------------------------- // A macro is used below because there may already be a pending
*** 1497,1508 **** Self->_Stalled = 0; assert(_owner != Self, "invariant"); ObjectWaiter::TStates v = node.TState; if (v == ObjectWaiter::TS_RUN) { ! const bool success = enter(Self); ! ADIM_guarantee(success, "enter signaled for a retry, but monitor should not have been deflated as waiters > 0"); } else { guarantee(v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant"); ReenterI(Self, &node); node.wait_reenter_end(this); } --- 1478,1488 ---- Self->_Stalled = 0; assert(_owner != Self, "invariant"); ObjectWaiter::TStates v = node.TState; if (v == ObjectWaiter::TS_RUN) { ! enter(Self); } else { guarantee(v == ObjectWaiter::TS_ENTER || v == ObjectWaiter::TS_CXQ, "invariant"); ReenterI(Self, &node); node.wait_reenter_end(this); }
*** 2062,2072 **** } DEBUG_ONLY(InitDone = true;) } ! // For internal used by ObjectSynchronizer::monitors_iterate(). ObjectMonitorHandle::ObjectMonitorHandle(ObjectMonitor * om_ptr) { om_ptr->inc_ref_count(); _om_ptr = om_ptr; } --- 2042,2052 ---- } DEBUG_ONLY(InitDone = true;) } ! // For internal use by ObjectSynchronizer::monitors_iterate(). ObjectMonitorHandle::ObjectMonitorHandle(ObjectMonitor * om_ptr) { om_ptr->inc_ref_count(); _om_ptr = om_ptr; }
*** 2096,2117 **** if (AsyncDeflateIdleMonitors) { // Race here if monitor is not owned! The above ref_count bump // will cause subsequent async deflation to skip it. However, // previous or concurrent async deflation is a race. ! if (om_ptr->_owner == DEFLATER_MARKER && om_ptr->_contentions <= 0) { ! // Async deflation is in progress. ! if (om_ptr->ref_count() <= 0) { ! // And our ref_count increment above lost the race to async ! // deflation. Attempt to restore the header/dmw to the ! // object's header so that we only retry once if the deflater ! // thread happens to be slow. om_ptr->install_displaced_markword_in_object(object); om_ptr->dec_ref_count(); return false; } - } // The ObjectMonitor could have been deflated and reused for // another object before we bumped the ref_count so make sure // our object still refers to this ObjectMonitor. const markOop tmp = object->mark(); if (!tmp->has_monitor() || tmp->monitor() != om_ptr) { --- 2076,2094 ---- if (AsyncDeflateIdleMonitors) { // Race here if monitor is not owned! The above ref_count bump // will cause subsequent async deflation to skip it. However, // previous or concurrent async deflation is a race. ! if (om_ptr->_owner == DEFLATER_MARKER && om_ptr->ref_count() <= 0) { ! // Async deflation is in progress and our ref_count increment ! // above lost the race to async deflation. Attempt to restore ! // the header/dmw to the object's header so that we only retry ! // once if the deflater thread happens to be slow. om_ptr->install_displaced_markword_in_object(object); om_ptr->dec_ref_count(); return false; } // The ObjectMonitor could have been deflated and reused for // another object before we bumped the ref_count so make sure // our object still refers to this ObjectMonitor. const markOop tmp = object->mark(); if (!tmp->has_monitor() || tmp->monitor() != om_ptr) {
*** 2120,2142 **** om_ptr->dec_ref_count(); return false; } } ! guarantee(_om_ptr == NULL, "sanity check: _om_ptr=" INTPTR_FORMAT, p2i(_om_ptr)); _om_ptr = om_ptr; return true; } // For internal use by ObjectSynchronizer::inflate(). void ObjectMonitorHandle::set_om_ptr(ObjectMonitor * om_ptr) { if (_om_ptr == NULL) { ! guarantee(om_ptr != NULL, "cannot clear an unset om_ptr"); om_ptr->inc_ref_count(); _om_ptr = om_ptr; } else { ! guarantee(om_ptr == NULL, "can only clear a set om_ptr"); _om_ptr->dec_ref_count(); _om_ptr = NULL; } } --- 2097,2119 ---- om_ptr->dec_ref_count(); return false; } } ! ADIM_guarantee(_om_ptr == NULL, "sanity check: _om_ptr=" INTPTR_FORMAT, p2i(_om_ptr)); _om_ptr = om_ptr; return true; } // For internal use by ObjectSynchronizer::inflate(). void ObjectMonitorHandle::set_om_ptr(ObjectMonitor * om_ptr) { if (_om_ptr == NULL) { ! ADIM_guarantee(om_ptr != NULL, "cannot clear an unset om_ptr"); om_ptr->inc_ref_count(); _om_ptr = om_ptr; } else { ! ADIM_guarantee(om_ptr == NULL, "can only clear a set om_ptr"); _om_ptr->dec_ref_count(); _om_ptr = NULL; } }
< prev index next >