< 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 >