< prev index next >
src/hotspot/share/runtime/synchronizer.cpp
Print this page
rev 54572 : Checkpoint latest preliminary review patches for full OpenJDK review; merge with 8222295.patch.
rev 54573 : imported patch dcubed.monitor_deflate_conc.v2.01
rev 54574 : imported patch dcubed.monitor_deflate_conc.v2.02
@@ -1173,10 +1173,19 @@
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);
+
+ assert(take->ref_count() >= 0, "must not be negative: ref_count=%d",
+ take->ref_count());
+ }
}
guarantee(!take->is_busy(), "invariant");
take->Recycle();
assert(take->is_free(), "invariant");
omRelease(Self, take, false);
@@ -1774,15 +1783,17 @@
//
// 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.
+// 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). Contending threads
-// that see those values know to retry their operation.
+// (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,
ObjectMonitor** freeTailp) {
assert(AsyncDeflateIdleMonitors, "sanity check");
@@ -1813,26 +1824,32 @@
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 racing threads to retry.
- // This is the second part of the async deflation dance.
+ // 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 && mid->ref_count() == 0) {
+ 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 racing threads to retry. If it is not, then we
+ // 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 the ObjectMonitor* is in use, then we have
- // lost that race. This is the third and final part of the async
- // deflation dance.
+ // 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: This ref_count check solves the race with save_om_ptr()
- // where its ref_count increment happens after the first ref_count
- // check in this function and before contentions is made negative.
+ // 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));
< prev index next >