< prev index next >

src/share/vm/runtime/safepoint.cpp

Print this page

        

@@ -53,10 +53,12 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/sweeper.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.inline.hpp"
 #include "services/runtimeService.hpp"
+#include "trace/tracing.hpp"
+#include "trace/traceMacros.hpp"
 #include "utilities/events.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/cms/concurrentMarkSweepThread.hpp"
 #include "gc/g1/suspendibleThreadSet.hpp"

@@ -77,14 +79,13 @@
 static volatile int TryingToBlock = 0 ;    // proximate value -- for advisory use only
 static bool timeout_error_printed = false;
 
 // Roll all threads forward to a safepoint and suspend them all
 void SafepointSynchronize::begin() {
-
+  EventSafepointBegin begin_event;
   Thread* myThread = Thread::current();
   assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint");
-
   if (PrintSafepointStatistics || PrintSafepointStatisticsTimeout > 0) {
     _safepoint_begin_time = os::javaTimeNanos();
     _ts_of_current_safepoint = tty->time_stamp().seconds();
   }
 

@@ -167,10 +168,14 @@
   //  5. In VM or Transitioning between states
   //     If a Java thread is currently running in the VM or transitioning
   //     between states, the safepointing code will wait for the thread to
   //     block itself when it attempts transitions to a new state.
   //
+  {
+    EventSafepointStateSync sync_event;
+    int initial_running = 0;
+
   _state            = _synchronizing;
   OrderAccess::fence();
 
   // Flush all thread states to memory
   if (!UseMembar) {

@@ -224,13 +229,16 @@
           cur_state->print_on(LogHandle(safepoint)::debug_stream());
         }
       }
     }
 
-    if (PrintSafepointStatistics && iterations == 0) {
+      if (iterations == 0) {
+        initial_running = still_running;
+        if (PrintSafepointStatistics) {
       begin_statistics(nof_threads, still_running);
     }
+      }
 
     if (still_running > 0) {
       // Check for if it takes to long
       if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
         print_safepoint_timeout(_spinning_timeout);

@@ -315,11 +323,24 @@
 
   if (PrintSafepointStatistics) {
     update_statistics_on_spin_end();
   }
 
+    if (sync_event.should_commit()) {
+      sync_event.set_safepointId(safepoint_counter());
+      sync_event.set_initialThreadCount(initial_running);
+      sync_event.set_runningThreadCount(_waiting_to_block);
+      sync_event.set_iterations(iterations);
+      sync_event.commit();
+    }
+  } //EventSafepointStateSync
+
   // wait until all threads are stopped
+  {
+    EventSafepointWaitBlocked wait_blocked_event;
+    int initial_waiting_to_block = _waiting_to_block;
+
   while (_waiting_to_block > 0) {
     log_debug(safepoint)("Waiting for %d thread(s) to block", _waiting_to_block);
     if (!SafepointTimeout || timeout_error_printed) {
       Safepoint_lock->wait(true);  // true, means with no safepoint checks
     } else {

@@ -352,10 +373,16 @@
 
   // Record state
   _state = _synchronized;
 
   OrderAccess::fence();
+    if (wait_blocked_event.should_commit()) {
+      wait_blocked_event.set_safepointId(safepoint_counter());
+      wait_blocked_event.set_runningThreadCount(initial_waiting_to_block);
+      wait_blocked_event.commit();
+    }
+  } // EventSafepointWaitBlocked
 
 #ifdef ASSERT
   for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
     // make sure all the threads were visited
     assert(cur->was_visited_for_critical_count(), "missed a thread");

@@ -375,21 +402,36 @@
   if (PrintSafepointStatistics) {
     update_statistics_on_sync_end(os::javaTimeNanos());
   }
 
   // Call stuff that needs to be run when a safepoint is just about to be completed
+  {
+    EventSafepointCleanup cleanup_event;
   do_cleanup_tasks();
+    if (cleanup_event.should_commit()) {
+      cleanup_event.set_safepointId(safepoint_counter());
+      cleanup_event.commit();
+    }
+  }
 
   if (PrintSafepointStatistics) {
     // Record how much time spend on the above cleanup tasks
     update_statistics_on_cleanup_end(os::javaTimeNanos());
   }
+  if (begin_event.should_commit()) {
+    begin_event.set_safepointId(safepoint_counter());
+    begin_event.set_totalThreadCount(nof_threads);
+    begin_event.set_jniCriticalThreadCount(_current_jni_active_count);
+    begin_event.commit();
+  }
 }
 
 // Wake up all threads, so they are ready to resume execution after the safepoint
 // operation has been carried out
 void SafepointSynchronize::end() {
+  EventSafepointEnd event;
+  int safepoint_id = safepoint_counter(); // Keep the odd counter as "id"
 
   assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
   assert((_safepoint_counter & 0x1) == 1, "must be odd");
   _safepoint_counter ++;
   // memory fence isn't required here since an odd _safepoint_counter

@@ -472,10 +514,15 @@
   }
 #endif // INCLUDE_ALL_GCS
   // record this time so VMThread can keep track how much time has elapsed
   // since last safepoint.
   _end_of_last_safepoint = os::javaTimeMillis();
+
+  if (event.should_commit()) {
+    event.set_safepointId(safepoint_id);
+    event.commit();
+  }
 }
 
 bool SafepointSynchronize::is_cleanup_needed() {
   // Need a safepoint if some inline cache buffers is non-empty
   if (!InlineCacheBuffer::is_empty()) return true;

@@ -485,43 +532,92 @@
 
 
 // Various cleaning tasks that should be done periodically at safepoints
 void SafepointSynchronize::do_cleanup_tasks() {
   {
-    TraceTime t1("deflating idle monitors", TraceSafepointCleanupTime);
+    const char* name = "deflating idle monitors";
+    EventSafepointCleanupTask event;
+    TraceTime t1(name, TraceSafepointCleanupTime);
     ObjectSynchronizer::deflate_idle_monitors();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
 
   {
-    TraceTime t2("updating inline caches", TraceSafepointCleanupTime);
+    const char* name = "updating inline caches";
+    EventSafepointCleanupTask event;
+    TraceTime t2(name, TraceSafepointCleanupTime);
     InlineCacheBuffer::update_inline_caches();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
   {
-    TraceTime t3("compilation policy safepoint handler", TraceSafepointCleanupTime);
+    const char* name = "compilation policy safepoint handler";
+    EventSafepointCleanupTask event;
+    TraceTime t3(name, TraceSafepointCleanupTime);
     CompilationPolicy::policy()->do_safepoint_work();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
 
   {
-    TraceTime t4("mark nmethods", TraceSafepointCleanupTime);
+    const char* name = "mark nmethods";
+    EventSafepointCleanupTask event;
+    TraceTime t4(name, TraceSafepointCleanupTime);
     NMethodSweeper::mark_active_nmethods();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
 
   if (SymbolTable::needs_rehashing()) {
-    TraceTime t5("rehashing symbol table", TraceSafepointCleanupTime);
+    const char* name = "rehashing symbol table";
+    EventSafepointCleanupTask event;
+    TraceTime t5(name, TraceSafepointCleanupTime);
     SymbolTable::rehash_table();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
 
   if (StringTable::needs_rehashing()) {
-    TraceTime t6("rehashing string table", TraceSafepointCleanupTime);
+    const char* name = "rehashing string table";
+    EventSafepointCleanupTask event;
+    TraceTime t6(name, TraceSafepointCleanupTime);
     StringTable::rehash_table();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
 
   {
     // CMS delays purging the CLDG until the beginning of the next safepoint and to
     // make sure concurrent sweep is done
-    TraceTime t7("purging class loader data graph", TraceSafepointCleanupTime);
+    const char* name = "purging class loader data graph";
+    EventSafepointCleanupTask event;
+    TraceTime t7(name, TraceSafepointCleanupTime);
     ClassLoaderDataGraph::purge_if_needed();
+    if (event.should_commit()) {
+      event.set_safepointId(safepoint_counter());
+      event.set_name(name);
+      event.commit();
+    }
   }
 }
 
 
 bool SafepointSynchronize::safepoint_safe(JavaThread *thread, JavaThreadState state) {
< prev index next >