< prev index next >

src/hotspot/share/runtime/synchronizer.cpp

Print this page
*** 2221,123 ***
      // Easy checks are first - the ObjectMonitor is busy or ObjectMonitor*
      // is in use so no deflation.
      return false;
    }
  
!   if (mid->try_set_owner_from(NULL, DEFLATER_MARKER) == NULL) {
!     // 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.
-       mid->try_set_owner_from(DEFLATER_MARKER, NULL);
-       return false;
-     }
  
!     if (Atomic::cmpxchg(&mid->_ref_count, (jint)0, -max_jint) == 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_is_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,
-                   p2i(mid->_EntryList));
- 
-         const oop obj = (oop) mid->object();
-         if (log_is_enabled(Trace, monitorinflation)) {
-           ResourceMark rm;
-           log_trace(monitorinflation)("deflate_monitor_using_JT: "
-                                       "object=" INTPTR_FORMAT ", mark="
-                                       INTPTR_FORMAT ", type='%s'",
-                                       p2i(obj), obj->mark().value(),
-                                       obj->klass()->external_name());
-         }
  
!         // Install the old mark word if nobody else has already done it.
!         mid->install_displaced_markword_in_object(obj);
!         mid->clear_using_JT();
  
!         assert(mid->object() == NULL, "must be NULL: object=" INTPTR_FORMAT,
!                p2i(mid->object()));
!         assert(mid->is_free(), "must be free: allocation_state=%d",
!                (int) mid->allocation_state());
  
-         // Move the deflated ObjectMonitor to the working free list
-         // defined by free_head_p and free_tail_p.
-         if (*free_head_p == NULL) {
-           // First one on the list.
-           *free_head_p = mid;
-         }
-         if (*free_tail_p != NULL) {
-           // We append to the list so the caller can use mid->_next_om
-           // to fix the linkages in its context.
-           ObjectMonitor* prevtail = *free_tail_p;
-           // Should have been cleaned up by the caller:
-           om_lock(prevtail);
  #ifdef ASSERT
!           ObjectMonitor* l_next_om = unmarked_next(prevtail);
  #endif
!           assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om));
!           prevtail->set_next_om(mid);  // prevtail now points to mid (and is unlocked)
!         }
!         *free_tail_p = mid;
- 
-         // At this point, mid->_next_om still refers to its current
-         // value and another ObjectMonitor's _next_om 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(&mid->_ref_count, max_jint);
  
  #ifdef ASSERT
!       jint l_ref_count = mid->ref_count();
  #endif
!       assert(l_ref_count >= 0, "must not be negative: l_ref_count=%d, ref_count=%d",
!              l_ref_count, 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:
-     mid->try_set_owner_from(DEFLATER_MARKER, NULL);
    }
  
!   // The owner field is no longer NULL so we lost the race since the
!   // ObjectMonitor is now busy.
!   return false;
  }
  
  // Walk a given monitor list, and deflate idle monitors.
  // The given list could be a per-thread list or a global list.
  //
--- 2221,122 ---
      // Easy checks are first - the ObjectMonitor is busy or ObjectMonitor*
      // is in use so no deflation.
      return false;
    }
  
!   if (mid->try_set_owner_from(NULL, DEFLATER_MARKER) != NULL) {
!     // The owner field is no longer NULL so we lost the race since the
!     // ObjectMonitor is now busy.
!     return false;
!   }
!   // 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.
!     mid->try_set_owner_from(DEFLATER_MARKER, NULL);
!     return false;
!   }
  
!   // 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 (Atomic::cmpxchg(&mid->_ref_count, (jint)0, -max_jint) != 0) {
+     // 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:
+     mid->try_set_owner_from(DEFLATER_MARKER, NULL);
+     return false;
+   }
  
!   if (!mid->owner_is_DEFLATER_MARKER()) {
!     // 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(&mid->_ref_count, max_jint);
  
  #ifdef ASSERT
!     jint l_ref_count = mid->ref_count();
  #endif
!     assert(l_ref_count >= 0, "must not be negative: l_ref_count=%d, ref_count=%d",
!            l_ref_count, mid->ref_count());
!     return false;
!   }
  
!   // 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,
+             p2i(mid->_EntryList));
+ 
+   const oop obj = (oop) mid->object();
+   if (log_is_enabled(Trace, monitorinflation)) {
+     ResourceMark rm;
+     log_trace(monitorinflation)("deflate_monitor_using_JT: "
+                                 "object=" INTPTR_FORMAT ", mark="
+                                 INTPTR_FORMAT ", type='%s'",
+                                 p2i(obj), obj->mark().value(),
+                                 obj->klass()->external_name());
+   }
+ 
+   // Install the old mark word if nobody else has already done it.
+   mid->install_displaced_markword_in_object(obj);
+   mid->clear_using_JT();
+ 
+   assert(mid->object() == NULL, "must be NULL: object=" INTPTR_FORMAT,
+          p2i(mid->object()));
+   assert(mid->is_free(), "must be free: allocation_state=%d",
+          (int) mid->allocation_state());
  
+   // Move the deflated ObjectMonitor to the working free list
+   // defined by free_head_p and free_tail_p.
+   if (*free_head_p == NULL) {
+     // First one on the list.
+     *free_head_p = mid;
+   }
+   if (*free_tail_p != NULL) {
+     // We append to the list so the caller can use mid->_next_om
+     // to fix the linkages in its context.
+     ObjectMonitor* prevtail = *free_tail_p;
+     // Should have been cleaned up by the caller:
+     om_lock(prevtail);
  #ifdef ASSERT
!     ObjectMonitor* l_next_om = unmarked_next(prevtail);
  #endif
!     assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om));
!     prevtail->set_next_om(mid);  // prevtail now points to mid (and is unlocked)
    }
+   *free_tail_p = mid;
  
!   // At this point, mid->_next_om still refers to its current
!   // value and another ObjectMonitor's _next_om 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.
  }
  
  // Walk a given monitor list, and deflate idle monitors.
  // The given list could be a per-thread list or a global list.
  //
< prev index next >