< prev index next >

src/share/vm/runtime/safepoint.cpp

Print this page
rev 13047 : [mq]: 8180932.patch

@@ -69,10 +69,14 @@
 #endif
 
 // --------------------------------------------------------------------------------------------------
 // Implementation of Safepoint begin/end
 
+WorkGang* SafepointSynchronize::_cleanup_workers = NULL;
+SubTasksDone* SafepointSynchronize::_cleanup_subtasks = NULL;
+uint SafepointSynchronize::_num_cleanup_workers = 0;
+
 SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized;
 volatile int  SafepointSynchronize::_waiting_to_block = 0;
 volatile int SafepointSynchronize::_safepoint_counter = 0;
 int SafepointSynchronize::_current_jni_active_count = 0;
 long  SafepointSynchronize::_end_of_last_safepoint = 0;

@@ -536,70 +540,134 @@
     event.set_name(name);
     event.commit();
   }
 }
 
-// Various cleaning tasks that should be done periodically at safepoints
-void SafepointSynchronize::do_cleanup_tasks() {
-  {
+class ParallelSPCleanupThreadClosure : public ThreadClosure {
+private:
+  CodeBlobClosure* _nmethod_cl;
+
+public:
+  ParallelSPCleanupThreadClosure() {
+    _nmethod_cl = NMethodSweeper::prepare_mark_active_nmethods();
+  }
+
+  void do_thread(Thread* thread) {
+    ObjectSynchronizer::deflate_thread_local_monitors(thread);
+    if (_nmethod_cl != NULL && thread->is_Java_thread() &&
+        ! thread->is_Code_cache_sweeper_thread()) {
+      JavaThread* jt = (JavaThread*) thread;
+      jt->nmethods_do(_nmethod_cl);
+    }
+  }
+};
+
+class ParallelSPCleanupTask : public AbstractGangTask {
+private:
+  SubTasksDone* _subtasks;
+  ParallelSPCleanupThreadClosure _cleanup_threads_cl;
+public:
+  ParallelSPCleanupTask(SubTasksDone* subtasks) :
+    AbstractGangTask("Parallel Safepoint Cleanup"),
+    _cleanup_threads_cl(ParallelSPCleanupThreadClosure()),
+    _subtasks(subtasks) {}
+
+  void work(uint worker_id) {
+    // All threads deflate monitors and mark nmethods (if necessary).
+    Threads::parallel_java_threads_do(&_cleanup_threads_cl);
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_DEFLATE_MONITORS)) {
     const char* name = "deflating idle monitors";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     ObjectSynchronizer::deflate_idle_monitors();
     event_safepoint_cleanup_task_commit(event, name);
   }
 
-  {
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_UPDATE_INLINE_CACHES)) {
     const char* name = "updating inline caches";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     InlineCacheBuffer::update_inline_caches();
     event_safepoint_cleanup_task_commit(event, name);
   }
-  {
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_COMPILATION_POLICY)) {
     const char* name = "compilation policy safepoint handler";
     EventSafepointCleanupTask event;
     TraceTime timer("compilation policy safepoint handler", TRACETIME_LOG(Info, safepoint, cleanup));
     CompilationPolicy::policy()->do_safepoint_work();
     event_safepoint_cleanup_task_commit(event, name);
   }
 
-  {
-    const char* name = "mark nmethods";
-    EventSafepointCleanupTask event;
-    TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
-    NMethodSweeper::mark_active_nmethods();
-    event_safepoint_cleanup_task_commit(event, name);
-  }
-
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH)) {
   if (SymbolTable::needs_rehashing()) {
     const char* name = "rehashing symbol table";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     SymbolTable::rehash_table();
     event_safepoint_cleanup_task_commit(event, name);
   }
+    }
 
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_STRING_TABLE_REHASH)) {
   if (StringTable::needs_rehashing()) {
     const char* name = "rehashing string table";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     StringTable::rehash_table();
     event_safepoint_cleanup_task_commit(event, name);
   }
+    }
 
-  {
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_CLD_PURGE)) {
     // CMS delays purging the CLDG until the beginning of the next safepoint and to
     // make sure concurrent sweep is done
     const char* name = "purging class loader data graph";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     ClassLoaderDataGraph::purge_if_needed();
     event_safepoint_cleanup_task_commit(event, name);
   }
-}
+    _subtasks->all_tasks_completed(SafepointSynchronize::_num_cleanup_workers);
+  }
+};
+
+// Various cleaning tasks that should be done periodically at safepoints
+void SafepointSynchronize::do_cleanup_tasks() {
+  if (_num_cleanup_workers == 0) {
+    // Deferred initialization.
+    if (ParallelSafepointCleanup) {
+      assert(_cleanup_workers == NULL, "already initialized?");
+      // Ask the GC to share its workers.
+      CollectedHeap* heap = Universe::heap();
+      assert(heap != NULL, "heap not initialized yet?");
+      _cleanup_workers = heap->get_safepoint_workers();
+      if (_cleanup_workers == NULL) {
+        // If GC doesn't want to share or doesn't even use worker threads, we create our own thread pool.
+        _cleanup_workers = new WorkGang("Parallel Safepoint Cleanup", ParallelSafepointCleanupThreads, false, false);
+        _cleanup_workers->initialize_workers();
+      }
+      _num_cleanup_workers = MIN2(ParallelSafepointCleanupThreads, _cleanup_workers->total_workers());
+    } else {
+      _num_cleanup_workers = 1;
+    }
+    assert(_num_cleanup_workers != 0, "not initialized?");
+    _cleanup_subtasks = new SubTasksDone(SAFEPOINT_CLEANUP_NUM_TASKS);
+  }
 
+  // Run cleanup serially or in parallel.
+  ParallelSPCleanupTask cleanup(_cleanup_subtasks);
+  StrongRootsScope srs(_num_cleanup_workers);
+  if (ParallelSafepointCleanup) {
+    assert(_cleanup_workers != NULL, "no cleanup workers?");
+    _cleanup_workers->run_task(&cleanup, _num_cleanup_workers);
+  } else {
+    assert(_num_cleanup_workers == 1, "only 1 thread");
+    cleanup.work(0);
+  }
+}
 
 bool SafepointSynchronize::safepoint_safe(JavaThread *thread, JavaThreadState state) {
   switch(state) {
   case _thread_in_native:
     // native threads are safe if they have no java stack or have walkable stack
< prev index next >