< prev index next >

src/hotspot/share/runtime/synchronizer.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

*** 348,359 **** // Interpreter/Compiler Slow Case // This routine is used to handle interpreter/compiler slow case // We don't need to use fast path here, because it must have been // failed in the interpreter/compiler code. void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) { - bool do_loop = true; - while (do_loop) { markOop mark = obj->mark(); assert(!mark->has_bias_pattern(), "should not see bias pattern here"); if (mark->is_neutral()) { // Anticipate successful CAS -- the ST of the displaced mark must --- 348,357 ----
*** 376,387 **** // must be non-zero to avoid looking like a re-entrant lock, // and must not look locked either. lock->set_displaced_header(markOopDesc::unused_mark()); ObjectMonitorHandle omh; inflate(&omh, THREAD, obj(), inflate_cause_monitor_enter); ! do_loop = !omh.om_ptr()->enter(THREAD); ! } } // This routine is used to handle interpreter/compiler slow case // We don't need to use fast path here, because it must have // failed in the interpreter/compiler code. Simply use the heavy --- 374,384 ---- // must be non-zero to avoid looking like a re-entrant lock, // and must not look locked either. lock->set_displaced_header(markOopDesc::unused_mark()); ObjectMonitorHandle omh; inflate(&omh, THREAD, obj(), inflate_cause_monitor_enter); ! omh.om_ptr()->enter(THREAD); } // This routine is used to handle interpreter/compiler slow case // We don't need to use fast path here, because it must have // failed in the interpreter/compiler code. Simply use the heavy
*** 419,434 **** if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } - bool do_loop = true; - while (do_loop) { ObjectMonitorHandle omh; inflate(&omh, THREAD, obj(), inflate_cause_vm_internal); ! do_loop = !omh.om_ptr()->reenter(recursion, THREAD); ! } } // ----------------------------------------------------------------------------- // JNI locks on java objects // NOTE: must use heavy weight monitor to handle jni monitor enter void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { --- 416,428 ---- if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } ObjectMonitorHandle omh; inflate(&omh, THREAD, obj(), inflate_cause_vm_internal); ! omh.om_ptr()->reenter(recursion, THREAD); } // ----------------------------------------------------------------------------- // JNI locks on java objects // NOTE: must use heavy weight monitor to handle jni monitor enter void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
*** 436,451 **** if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } THREAD->set_current_pending_monitor_is_from_java(false); - bool do_loop = true; - while (do_loop) { ObjectMonitorHandle omh; inflate(&omh, THREAD, obj(), inflate_cause_jni_enter); ! do_loop = !omh.om_ptr()->enter(THREAD); ! } THREAD->set_current_pending_monitor_is_from_java(true); } // NOTE: must use heavy weight monitor to handle jni monitor exit void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) { --- 430,442 ---- if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } THREAD->set_current_pending_monitor_is_from_java(false); ObjectMonitorHandle omh; inflate(&omh, THREAD, obj(), inflate_cause_jni_enter); ! omh.om_ptr()->enter(THREAD); THREAD->set_current_pending_monitor_is_from_java(true); } // NOTE: must use heavy weight monitor to handle jni monitor exit void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
*** 1172,1182 **** guarantee(take->object() == NULL, "invariant"); if (AsyncDeflateIdleMonitors) { // Clear any values we allowed to linger during async deflation. take->_header = NULL; take->set_owner(NULL); - take->_contentions = 0; if (take->ref_count() < 0) { // Add back max_jint to restore the ref_count field to its // proper value. Atomic::add(max_jint, &take->_ref_count); --- 1163,1172 ----
*** 1780,1797 **** // Deflate the specified ObjectMonitor if not in-use using a JavaThread. // Returns true if it was deflated and false otherwise. // // The async deflation protocol sets owner to DEFLATER_MARKER and ! // makes contentions negative as signals to contending threads that // an async deflation is in progress. There are a number of checks // as part of the protocol to make sure that the calling thread has // not lost the race to a contending thread or to a thread that just // wants to use the ObjectMonitor*. // // The ObjectMonitor has been successfully async deflated when: ! // (owner == DEFLATER_MARKER && contentions < 0 && ref_count < 0). // Contending threads or ObjectMonitor* using threads that see those // values know to retry their operation. // bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid, ObjectMonitor** freeHeadp, --- 1770,1787 ---- // Deflate the specified ObjectMonitor if not in-use using a JavaThread. // Returns true if it was deflated and false otherwise. // // The async deflation protocol sets owner to DEFLATER_MARKER and ! // makes ref_count negative as signals to contending threads that // an async deflation is in progress. There are a number of checks // as part of the protocol to make sure that the calling thread has // not lost the race to a contending thread or to a thread that just // wants to use the ObjectMonitor*. // // The ObjectMonitor has been successfully async deflated when: ! // (owner == DEFLATER_MARKER && ref_count < 0) // Contending threads or ObjectMonitor* using threads that see those // values know to retry their operation. // bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid, ObjectMonitor** freeHeadp,
*** 1813,1857 **** // ObjectMonitor is not owned by another thread. Our setting // owner to DEFLATER_MARKER forces any contending thread through // the slow path. This is just the first part of the async // deflation dance. ! if (mid->_waiters != 0 || mid->ref_count() != 0) { // Another thread has raced to enter the ObjectMonitor after ! // mid->is_busy() above and has already waited on it which ! // makes it busy so no deflation. Or the ObjectMonitor* is ! // in use for some other operation like inflate(). Restore ! // owner to NULL if it is still DEFLATER_MARKER. Atomic::cmpxchg((void*)NULL, &mid->_owner, DEFLATER_MARKER); return false; } ! if (Atomic::cmpxchg(-max_jint, &mid->_contentions, (jint)0) == 0) { ! // Make contentions negative to force any contending threads to ! // retry. This is the second part of the async deflation dance. ! if (mid->_owner == DEFLATER_MARKER && ! Atomic::cmpxchg(-max_jint, &mid->_ref_count, (jint)0) == 0) { // If owner is still DEFLATER_MARKER, then we have successfully // signaled any contending threads to retry. If it is not, then we // have lost the race to an entering thread and the ObjectMonitor ! // is now busy. If we cannot make ref_count negative (because the ! // ObjectMonitor* is in use), then we have lost that race instead. ! // This is the third and final part of the async deflation dance. ! // Note: This owner check solves the ABA problem with contentions // where another thread acquired the ObjectMonitor, finished ! // using it and restored the contentions to zero. ! // Note: Making ref_count negative solves the race with ! // ObjectMonitor::save_om_ptr() where its ref_count increment ! // happens after the first ref_count check in this function. ! // Note: Making ref_count negative must happen after the third ! // part check of "owner == DEFLATER_MARKER". When save_om_ptr() ! // retries, it will call install_displaced_markword_in_object() ! // which will disconnect the object from the ObjectMonitor so ! // deflation must happen. // Sanity checks for the races: guarantee(mid->_waiters == 0, "must be 0: waiters=%d", mid->_waiters); guarantee(mid->_cxq == NULL, "must be no contending threads: cxq=" INTPTR_FORMAT, p2i(mid->_cxq)); guarantee(mid->_EntryList == NULL, "must be no entering threads: EntryList=" INTPTR_FORMAT, --- 1803,1839 ---- // ObjectMonitor is not owned by another thread. Our setting // owner to DEFLATER_MARKER forces any contending thread through // the slow path. This is just the first part of the async // deflation dance. ! if (mid->_contentions != 0 || mid->_waiters != 0) { // Another thread has raced to enter the ObjectMonitor after ! // mid->is_busy() above or has already entered and waited on ! // it which makes it busy so no deflation. Restore owner to ! // NULL if it is still DEFLATER_MARKER. Atomic::cmpxchg((void*)NULL, &mid->_owner, DEFLATER_MARKER); return false; } ! if (Atomic::cmpxchg(-max_jint, &mid->_ref_count, (jint)0) == 0) { ! // Make ref_count negative to force any contending threads or ! // ObjectMonitor* using threads to retry. This is the second ! // part of the async deflation dance. ! if (mid->_owner == DEFLATER_MARKER) { // If owner is still DEFLATER_MARKER, then we have successfully // signaled any contending threads to retry. If it is not, then we // have lost the race to an entering thread and the ObjectMonitor ! // is now busy. This is the third and final part of the async ! // deflation dance. ! // Note: This owner check solves the ABA problem with ref_count // where another thread acquired the ObjectMonitor, finished ! // using it and restored the ref_count to zero. // Sanity checks for the races: + guarantee(mid->_contentions == 0, "must be 0: contentions=%d", + mid->_contentions); guarantee(mid->_waiters == 0, "must be 0: waiters=%d", mid->_waiters); guarantee(mid->_cxq == NULL, "must be no contending threads: cxq=" INTPTR_FORMAT, p2i(mid->_cxq)); guarantee(mid->_EntryList == NULL, "must be no entering threads: EntryList=" INTPTR_FORMAT,
*** 1896,1928 **** // At this point, mid->FreeNext still refers to its current // value and another ObjectMonitor's FreeNext field still // refers to this ObjectMonitor. Those linkages have to be // cleaned up by the caller who has the complete context. ! // We leave owner == DEFLATER_MARKER and contentions < 0 // to force any racing threads to retry. return true; // Success, ObjectMonitor has been deflated. } ! // The owner was changed from DEFLATER_MARKER or ObjectMonitor* ! // is in use so we lost the race since the ObjectMonitor is now ! // busy. ! ! // Restore owner to NULL if it is still DEFLATER_MARKER: ! Atomic::cmpxchg((void*)NULL, &mid->_owner, DEFLATER_MARKER); ! // Add back max_jint to restore the contentions field to its // proper value (which may not be what we saw above): ! Atomic::add(max_jint, &mid->_contentions); ! assert(mid->_contentions >= 0, "must not be negative: contentions=%d", ! mid->_contentions); } ! // The contentions was no longer 0 so we lost the race since the ! // ObjectMonitor is now busy. ! assert(mid->_owner != DEFLATER_MARKER, "must not be DEFLATER_MARKER"); } // The owner field is no longer NULL so we lost the race since the // ObjectMonitor is now busy. return false; --- 1878,1908 ---- // At this point, mid->FreeNext still refers to its current // value and another ObjectMonitor's FreeNext field still // refers to this ObjectMonitor. Those linkages have to be // cleaned up by the caller who has the complete context. ! // We leave owner == DEFLATER_MARKER and ref_count < 0 // to force any racing threads to retry. return true; // Success, ObjectMonitor has been deflated. } ! // The owner was changed from DEFLATER_MARKER so we lost the ! // race since the ObjectMonitor is now busy. ! // Add back max_jint to restore the ref_count field to its // proper value (which may not be what we saw above): ! Atomic::add(max_jint, &mid->_ref_count); ! assert(mid->ref_count() >= 0, "must not be negative: ref_count=%d", ! mid->ref_count()); ! return false; } ! // The ref_count was no longer 0 so we lost the race since the ! // ObjectMonitor is now busy or the ObjectMonitor* is now is use. ! // Restore owner to NULL if it is still DEFLATER_MARKER: ! Atomic::cmpxchg((void*)NULL, &mid->_owner, DEFLATER_MARKER); } // The owner field is no longer NULL so we lost the race since the // ObjectMonitor is now busy. return false;
< prev index next >