< prev index next >

src/hotspot/share/runtime/synchronizer.cpp

Print this page
rev 59757 : Add whitebox support for deflating idle monitors including ObjectSynchronizer::request_deflate_idle_monitors(); drop ObjectSynchronizer::_is_special_deflation_requested flag, functions and uses; switch to ObjectSynchronizer::request_deflate_idle_monitors() as needed; _last_async_deflation_time_ns should be set at the end of async deflation;

@@ -119,11 +119,10 @@
 static volatile intptr_t gInflationLocks[NINFLATIONLOCKS];
 
 // global list of blocks of monitors
 PaddedObjectMonitor* ObjectSynchronizer::g_block_list = NULL;
 bool volatile ObjectSynchronizer::_is_async_deflation_requested = false;
-bool volatile ObjectSynchronizer::_is_special_deflation_requested = false;
 jlong ObjectSynchronizer::_last_async_deflation_time_ns = 0;
 
 struct ObjectMonitorListGlobals {
   char         _pad_prefix[OM_CACHE_LINE_SIZE];
   // These are highly shared list related variables.

@@ -1307,11 +1306,10 @@
       monitors_used_above_threshold()) {
     // It's been longer than our specified deflate interval and there
     // are too many monitors in use. We don't deflate more frequently
     // than AsyncDeflationInterval (unless is_async_deflation_requested)
     // in order to not swamp the ServiceThread.
-    _last_async_deflation_time_ns = os::javaTimeNanos();
     return true;
   }
   return false;
 }
 

@@ -1321,20 +1319,55 @@
       // Too many monitors in use.
       return true;
     }
     return false;
   }
-  if (is_special_deflation_requested()) {
-    // For AsyncDeflateIdleMonitors only do a safepoint deflation
-    // if there is a special deflation request.
-    return true;
-  }
   return false;
 }
 
+bool ObjectSynchronizer::request_deflate_idle_monitors() {
+  bool is_JavaThread = Thread::current()->is_Java_thread();
+  bool ret_code = false;
+
+  if (AsyncDeflateIdleMonitors) {
+    jlong last_time = last_async_deflation_time_ns();
+    set_is_async_deflation_requested(true);
+    {
+      MonitorLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+      ml.notify_all();
+    }
+    const int N_CHECKS = 5;
+    for (int i = 0; i < N_CHECKS; i++) {  // sleep for at most 5 seconds
+      if (last_async_deflation_time_ns() > last_time) {
+        log_info(monitorinflation)("Async Deflation happened after %d check(s).", i);
+        ret_code = true;
+        break;
+      }
+      if (is_JavaThread) {
+        // JavaThread has to honor the blocking protocol.
+        ThreadBlockInVM tbivm(JavaThread::current());
+        os::naked_short_sleep(999);  // sleep for almost 1 second
+      } else {
+        os::naked_short_sleep(999);  // sleep for almost 1 second
+      }
+    }
+    if (ret_code == false) {
+      log_info(monitorinflation)("Async Deflation DID NOT happen after %d checks.", N_CHECKS);
+    }
+  } else if (!Thread::current()->is_VM_thread()) {
+    // The VMThread only calls this at shutdown time before the final
+    // safepoint so it should not need to force this safepoint.
+    VM_ForceSafepoint force_safepoint_op;
+    VMThread::execute(&force_safepoint_op);
+    ret_code = true;
+  }
+
+  return ret_code;
+}
+
 jlong ObjectSynchronizer::time_since_last_async_deflation_ms() {
-  return (os::javaTimeNanos() - _last_async_deflation_time_ns) / (NANOUNITS / MILLIUNITS);
+  return (os::javaTimeNanos() - last_async_deflation_time_ns()) / (NANOUNITS / MILLIUNITS);
 }
 
 void ObjectSynchronizer::oops_do(OopClosure* f) {
   // We only scan the global used list here (for moribund threads), and
   // the thread-local monitors in Thread::oops_do().

@@ -2015,13 +2048,12 @@
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
   // The per-thread in-use lists are handled in
   // ParallelSPCleanupThreadClosure::do_thread().
 
-  if (!AsyncDeflateIdleMonitors || is_special_deflation_requested()) {
-    // Use the older mechanism for the global in-use list or if a
-    // special deflation has been requested before the safepoint.
+  if (!AsyncDeflateIdleMonitors) {
+    // Use the older mechanism for the global in-use list.
     ObjectSynchronizer::deflate_idle_monitors(counters);
     return;
   }
 
   log_debug(monitorinflation)("requesting async deflation of idle monitors.");

@@ -2436,15 +2468,13 @@
 void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
   if (AsyncDeflateIdleMonitors) {
     // Nothing to do when global idle ObjectMonitors are deflated using
-    // a JavaThread unless a special deflation has been requested.
-    if (!is_special_deflation_requested()) {
+    // a JavaThread.
       return;
     }
-  }
 
   bool deflated = false;
 
   ObjectMonitor* free_head_p = NULL;  // Local SLL of scavenged monitors
   ObjectMonitor* free_tail_p = NULL;

@@ -2532,10 +2562,11 @@
                              Atomic::load(&om_list_globals._in_use_count),
                              Atomic::load(&om_list_globals._free_count),
                              Atomic::load(&om_list_globals._wait_count));
 
   // The ServiceThread's async deflation request has been processed.
+  _last_async_deflation_time_ns = os::javaTimeNanos();
   set_is_async_deflation_requested(false);
 
   if (Atomic::load(&om_list_globals._wait_count) > 0) {
     // There are deflated ObjectMonitors waiting for a handshake
     // (or a safepoint) for safety.

@@ -2607,20 +2638,10 @@
   } else {
     OM_PERFDATA_OP(MonExtant, inc(Atomic::load(&target->om_in_use_count)));
   }
 
   do {
-    if (saved_mid_in_use_p != NULL) {
-      // We looped around because deflate_monitor_list_using_JT()
-      // detected a pending safepoint. Honoring the safepoint is good,
-      // but as long as is_special_deflation_requested() is supported,
-      // we can't safely restart using saved_mid_in_use_p. That saved
-      // ObjectMonitor could have been deflated by safepoint based
-      // deflation and would no longer be on the in-use list where we
-      // originally found it.
-      saved_mid_in_use_p = NULL;
-    }
     int local_deflated_count;
     if (is_global) {
       local_deflated_count =
           deflate_monitor_list_using_JT(&om_list_globals._in_use_list,
                                         &om_list_globals._in_use_count,

@@ -2699,14 +2720,13 @@
   // monitors. Note: if the work is split among more than one
   // worker thread, then the reported time will likely be more
   // than a beginning to end measurement of the phase.
   log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->per_thread_times, counters->per_thread_scavenged);
 
-  bool needs_special_deflation = is_special_deflation_requested();
-  if (AsyncDeflateIdleMonitors && !needs_special_deflation) {
+  if (AsyncDeflateIdleMonitors) {
     // Nothing to do when idle ObjectMonitors are deflated using
-    // a JavaThread unless a special deflation has been requested.
+    // a JavaThread.
     return;
   }
 
   if (log_is_enabled(Debug, monitorinflation)) {
     // exit_globals()'s call to audit_and_print_stats() is done

@@ -2727,21 +2747,18 @@
   OM_PERFDATA_OP(Deflations, inc(counters->n_scavenged));
   OM_PERFDATA_OP(MonExtant, set_value(counters->n_in_circulation));
 
   GVars.stw_random = os::random();
   GVars.stw_cycle++;
-
-  if (needs_special_deflation) {
-    set_is_special_deflation_requested(false);  // special deflation is done
-  }
 }
 
 void ObjectSynchronizer::deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
-  if (AsyncDeflateIdleMonitors && !is_special_deflation_requested()) {
-    // Nothing to do if a special deflation has NOT been requested.
+  if (AsyncDeflateIdleMonitors) {
+    // Nothing to do when per-thread idle ObjectMonitors are deflated
+    // using a JavaThread.
     return;
   }
 
   ObjectMonitor* free_head_p = NULL;  // Local SLL of scavenged monitors
   ObjectMonitor* free_tail_p = NULL;
< prev index next >