changeset 10595:1b136ffa8a67

8140257: Add support for "gc service threads" to ConcurrentGCThread Summary: Push up the common run() and stop() methods from subclasses to ConcurrentGCThread, as well as declaration iof run_service() stop_service(). Reviewed-by: kbarrett, pliden
author drwhite
date Fri, 11 Mar 2016 16:59:58 -0500
parents e928b4b9e4ea
children e7bcc46ab8bd
files src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp src/share/vm/gc/cms/concurrentMarkSweepThread.cpp src/share/vm/gc/cms/concurrentMarkSweepThread.hpp src/share/vm/gc/g1/concurrentG1RefineThread.cpp src/share/vm/gc/g1/concurrentG1RefineThread.hpp src/share/vm/gc/g1/concurrentMarkThread.cpp src/share/vm/gc/g1/concurrentMarkThread.hpp src/share/vm/gc/g1/g1StringDedup.cpp src/share/vm/gc/g1/g1StringDedupThread.cpp src/share/vm/gc/g1/g1StringDedupThread.hpp src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp src/share/vm/gc/shared/concurrentGCThread.cpp src/share/vm/gc/shared/concurrentGCThread.hpp src/share/vm/gc/shared/genCollectedHeap.cpp
diffstat 15 files changed, 111 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -1412,7 +1412,7 @@
     if (_foregroundGCShouldWait) {
       // We are going to be waiting for action for the CMS thread;
       // it had better not be gone (for instance at shutdown)!
-      assert(ConcurrentMarkSweepThread::cmst() != NULL,
+      assert(ConcurrentMarkSweepThread::cmst() != NULL && !ConcurrentMarkSweepThread::cmst()->has_terminated(),
              "CMS thread must be running");
       // Wait here until the background collector gives us the go-ahead
       ConcurrentMarkSweepThread::clear_CMS_flag(
@@ -3648,7 +3648,7 @@
     // XXX FIX ME!!! YSR
     size_t loops = 0, workdone = 0, cumworkdone = 0, waited = 0;
     while (!(should_abort_preclean() ||
-             ConcurrentMarkSweepThread::should_terminate())) {
+             ConcurrentMarkSweepThread::cmst()->should_terminate())) {
       workdone = preclean_work(CMSPrecleanRefLists2, CMSPrecleanSurvivors2);
       cumworkdone += workdone;
       loops++;
--- a/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -42,7 +42,6 @@
 
 ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::_cmst = NULL;
 CMSCollector* ConcurrentMarkSweepThread::_collector         = NULL;
-bool ConcurrentMarkSweepThread::_should_terminate           = false;
 int  ConcurrentMarkSweepThread::_CMS_flag                   = CMS_nil;
 
 volatile jint ConcurrentMarkSweepThread::_pending_yields    = 0;
@@ -62,88 +61,60 @@
 
   set_name("CMS Main Thread");
 
-  if (os::create_thread(this, os::cgc_thread)) {
-    // An old comment here said: "Priority should be just less
-    // than that of VMThread".  Since the VMThread runs at
-    // NearMaxPriority, the old comment was inaccurate, but
-    // changing the default priority to NearMaxPriority-1
-    // could change current behavior, so the default of
-    // NearMaxPriority stays in place.
-    //
-    // Note that there's a possibility of the VMThread
-    // starving if UseCriticalCMSThreadPriority is on.
-    // That won't happen on Solaris for various reasons,
-    // but may well happen on non-Solaris platforms.
-    int native_prio;
-    if (UseCriticalCMSThreadPriority) {
-      native_prio = os::java_to_os_priority[CriticalPriority];
-    } else {
-      native_prio = os::java_to_os_priority[NearMaxPriority];
-    }
-    os::set_native_priority(this, native_prio);
+  // An old comment here said: "Priority should be just less
+  // than that of VMThread".  Since the VMThread runs at
+  // NearMaxPriority, the old comment was inaccurate, but
+  // changing the default priority to NearMaxPriority-1
+  // could change current behavior, so the default of
+  // NearMaxPriority stays in place.
+  //
+  // Note that there's a possibility of the VMThread
+  // starving if UseCriticalCMSThreadPriority is on.
+  // That won't happen on Solaris for various reasons,
+  // but may well happen on non-Solaris platforms.
+  create_and_start(UseCriticalCMSThreadPriority ? CriticalPriority : NearMaxPriority);
 
-    if (!DisableStartThread) {
-      os::start_thread(this);
-    }
-  }
   _sltMonitor = SLT_lock;
 }
 
-void ConcurrentMarkSweepThread::run() {
+void ConcurrentMarkSweepThread::run_service() {
   assert(this == cmst(), "just checking");
 
-  initialize_in_thread();
-  // From this time Thread::current() should be working.
-  assert(this == Thread::current(), "just checking");
   if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) {
     log_warning(gc)("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread);
   }
-  // Wait until Universe::is_fully_initialized()
+
   {
-    CMSLoopCountWarn loopX("CMS::run", "waiting for "
-                           "Universe::is_fully_initialized()", 2);
     MutexLockerEx x(CGC_lock, true);
     set_CMS_flag(CMS_cms_wants_token);
-    // Wait until Universe is initialized and all initialization is completed.
-    while (!is_init_completed() && !Universe::is_fully_initialized() &&
-           !_should_terminate) {
-      CGC_lock->wait(true, 200);
-      loopX.tick();
-    }
+    assert(is_init_completed() && Universe::is_fully_initialized(), "ConcurrentGCThread::run() should have waited for this.");
+
     // Wait until the surrogate locker thread that will do
     // pending list locking on our behalf has been created.
     // We cannot start the SLT thread ourselves since we need
     // to be a JavaThread to do so.
     CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2);
-    while (_slt == NULL && !_should_terminate) {
+    while (_slt == NULL && !should_terminate()) {
       CGC_lock->wait(true, 200);
       loopY.tick();
     }
     clear_CMS_flag(CMS_cms_wants_token);
   }
 
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     sleepBeforeNextCycle();
-    if (_should_terminate) break;
+    if (should_terminate()) break;
     GCIdMark gc_id_mark;
     GCCause::Cause cause = _collector->_full_gc_requested ?
       _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;
     _collector->collect_in_background(cause);
   }
-  assert(_should_terminate, "just checking");
+
   // Check that the state of any protocol for synchronization
   // between background (CMS) and foreground collector is "clean"
   // (i.e. will not potentially block the foreground collector,
   // requiring action by us).
   verify_ok_to_terminate();
-  // Signal that it is terminated
-  {
-    MutexLockerEx mu(Terminator_lock,
-                     Mutex::_no_safepoint_check_flag);
-    assert(_cmst == this, "Weird!");
-    _cmst = NULL;
-    Terminator_lock->notify();
-  }
 }
 
 #ifndef PRODUCT
@@ -157,39 +128,24 @@
 
 // create and start a new ConcurrentMarkSweep Thread for given CMS generation
 ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) {
-  if (!_should_terminate) {
-    assert(cmst() == NULL, "start() called twice?");
-    ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector);
-    assert(cmst() == th, "Where did the just-created CMS thread go?");
-    return th;
-  }
-  return NULL;
+  guarantee(_cmst == NULL, "start() called twice!");
+  ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector);
+  assert(_cmst == th, "Where did the just-created CMS thread go?");
+  return th;
 }
 
-void ConcurrentMarkSweepThread::stop() {
-  // it is ok to take late safepoints here, if needed
-  {
-    MutexLockerEx x(Terminator_lock);
-    _should_terminate = true;
-  }
-  { // Now post a notify on CGC_lock so as to nudge
-    // CMS thread(s) that might be slumbering in
-    // sleepBeforeNextCycle.
-    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
-    CGC_lock->notify_all();
-  }
-  { // Now wait until (all) CMS thread(s) have exited
-    MutexLockerEx x(Terminator_lock);
-    while(cmst() != NULL) {
-      Terminator_lock->wait();
-    }
-  }
+void ConcurrentMarkSweepThread::stop_service() {
+  // Now post a notify on CGC_lock so as to nudge
+  // CMS thread(s) that might be slumbering in
+  // sleepBeforeNextCycle.
+  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+  CGC_lock->notify_all();
 }
 
 void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) {
   assert(tc != NULL, "Null ThreadClosure");
-  if (_cmst != NULL) {
-    tc->do_thread(_cmst);
+  if (cmst() != NULL && !cmst()->has_terminated()) {
+    tc->do_thread(cmst());
   }
   assert(Universe::is_fully_initialized(),
          "Called too early, make sure heap is fully initialized");
@@ -202,8 +158,8 @@
 }
 
 void ConcurrentMarkSweepThread::print_all_on(outputStream* st) {
-  if (_cmst != NULL) {
-    _cmst->print_on(st);
+  if (cmst() != NULL && !cmst()->has_terminated()) {
+    cmst()->print_on(st);
     st->cr();
   }
   if (_collector != NULL) {
@@ -278,7 +234,7 @@
 void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
   MutexLockerEx x(CGC_lock,
                   Mutex::_no_safepoint_check_flag);
-  if (_should_terminate || _collector->_full_gc_requested) {
+  if (should_terminate() || _collector->_full_gc_requested) {
     return;
   }
   set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
@@ -307,7 +263,7 @@
 
   unsigned int loop_count = 0;
 
-  while(!_should_terminate) {
+  while(!should_terminate()) {
     double now_time = os::elapsedTime();
     long wait_time_millis;
 
@@ -327,7 +283,7 @@
     {
       MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
 
-      if (_should_terminate || _collector->_full_gc_requested) {
+      if (should_terminate() || _collector->_full_gc_requested) {
         return;
       }
       set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
@@ -364,7 +320,7 @@
 }
 
 void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     if(CMSWaitDuration >= 0) {
       // Wait until the next synchronous GC, a concurrent full gc
       // request or a timeout, whichever is earlier.
--- a/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Fri Mar 11 16:59:58 2016 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,8 +37,6 @@
   friend class VMStructs;
   friend class ConcurrentMarkSweepGeneration;   // XXX should remove friendship
   friend class CMSCollector;
- public:
-  virtual void run();
 
  private:
   static ConcurrentMarkSweepThread*     _cmst;
@@ -47,8 +45,6 @@
   static SurrogateLockerThread::SLT_msg_type _sltBuffer;
   static Monitor*                       _sltMonitor;
 
-  static bool _should_terminate;
-
   enum CMS_flag_type {
     CMS_nil             = NoBits,
     CMS_cms_wants_token = nth_bit(0),
@@ -72,6 +68,9 @@
   // debugging
   void verify_ok_to_terminate() const PRODUCT_RETURN;
 
+  void run_service();
+  void stop_service();
+
  public:
   // Constructor
   ConcurrentMarkSweepThread(CMSCollector* collector);
@@ -91,8 +90,6 @@
 
   // Create and start the CMS Thread, or stop it on shutdown
   static ConcurrentMarkSweepThread* start(CMSCollector* collector);
-  static void stop();
-  static bool should_terminate() { return _should_terminate; }
 
   // Synchronization using CMS token
   static void synchronize(bool is_cms_thread);
--- a/src/share/vm/gc/g1/concurrentG1RefineThread.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/concurrentG1RefineThread.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -78,7 +78,7 @@
 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
-  while (!_should_terminate && !is_active()) {
+  while (!should_terminate() && !is_active()) {
     _monitor->wait(Mutex::_no_safepoint_check_flag);
   }
 }
@@ -109,22 +109,13 @@
   }
 }
 
-void ConcurrentG1RefineThread::run() {
-  initialize_in_thread();
-  wait_for_universe_init();
-
-  run_service();
-
-  terminate();
-}
-
 void ConcurrentG1RefineThread::run_service() {
   _vtime_start = os::elapsedVTime();
 
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     // Wait for work
     wait_for_completed_buffers();
-    if (_should_terminate) {
+    if (should_terminate()) {
       break;
     }
 
@@ -168,23 +159,6 @@
   log_debug(gc, refine)("Stopping %d", _worker_id);
 }
 
-void ConcurrentG1RefineThread::stop() {
-  // it is ok to take late safepoints here, if needed
-  {
-    MutexLockerEx mu(Terminator_lock);
-    _should_terminate = true;
-  }
-
-  stop_service();
-
-  {
-    MutexLockerEx mu(Terminator_lock);
-    while (!_has_terminated) {
-      Terminator_lock->wait();
-    }
-  }
-}
-
 void ConcurrentG1RefineThread::stop_service() {
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   _monitor->notify();
--- a/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Fri Mar 11 16:59:58 2016 -0500
@@ -72,7 +72,6 @@
   void stop_service();
 
 public:
-  virtual void run();
   // Constructor
   ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
                            CardTableEntryClosure* refine_closure,
@@ -84,9 +83,6 @@
   double vtime_accum() { return _vtime_accum; }
 
   ConcurrentG1Refine* cg1r() { return _cg1r;     }
-
-  // shutdown
-  void stop();
 };
 
 #endif // SHARE_VM_GC_G1_CONCURRENTG1REFINETHREAD_HPP
--- a/src/share/vm/gc/g1/concurrentMarkThread.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/concurrentMarkThread.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -105,25 +105,16 @@
   }
 };
 
-void ConcurrentMarkThread::run() {
-  initialize_in_thread();
-  wait_for_universe_init();
-
-  run_service();
-
-  terminate();
-}
-
 void ConcurrentMarkThread::run_service() {
   _vtime_start = os::elapsedVTime();
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1_policy = g1h->g1_policy();
 
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     // wait until started is set.
     sleepBeforeNextCycle();
-    if (_should_terminate) {
+    if (should_terminate()) {
       _cm->root_regions()->cancel_scan();
       break;
     }
@@ -293,22 +284,6 @@
   }
 }
 
-void ConcurrentMarkThread::stop() {
-  {
-    MutexLockerEx ml(Terminator_lock);
-    _should_terminate = true;
-  }
-
-  stop_service();
-
-  {
-    MutexLockerEx ml(Terminator_lock);
-    while (!_has_terminated) {
-      Terminator_lock->wait();
-    }
-  }
-}
-
 void ConcurrentMarkThread::stop_service() {
   MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
   CGC_lock->notify_all();
@@ -320,7 +295,7 @@
   assert(!in_progress(), "should have been cleared");
 
   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
-  while (!started() && !_should_terminate) {
+  while (!started() && !should_terminate()) {
     CGC_lock->wait(Mutex::_no_safepoint_check_flag);
   }
 
--- a/src/share/vm/gc/g1/concurrentMarkThread.hpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/concurrentMarkThread.hpp	Fri Mar 11 16:59:58 2016 -0500
@@ -38,13 +38,8 @@
 
   double _vtime_start;  // Initial virtual time.
   double _vtime_accum;  // Accumulated virtual time.
-
   double _vtime_mark_accum;
 
- public:
-  virtual void run();
-
- private:
   G1ConcurrentMark*                _cm;
 
   enum State {
@@ -93,9 +88,6 @@
   // as the CM thread might take some time to wake up before noticing
   // that started() is set and set in_progress().
   bool during_cycle()      { return !idle(); }
-
-  // shutdown
-  void stop();
 };
 
 #endif // SHARE_VM_GC_G1_CONCURRENTMARKTHREAD_HPP
--- a/src/share/vm/gc/g1/g1StringDedup.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/g1StringDedup.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
 
 void G1StringDedup::stop() {
   assert(is_enabled(), "String deduplication not enabled");
-  G1StringDedupThread::stop();
+  G1StringDedupThread::thread()->stop();
 }
 
 bool G1StringDedup::is_candidate_from_mark(oop obj) {
--- a/src/share/vm/gc/g1/g1StringDedupThread.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/g1StringDedupThread.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,11 +81,9 @@
   StringTable::shared_oops_do(&sharedStringDedup);
 }
 
-void G1StringDedupThread::run() {
+void G1StringDedupThread::run_service() {
   G1StringDedupStat total_stat;
 
-  initialize_in_thread();
-  wait_for_universe_init();
   deduplicate_shared_strings(total_stat);
 
   // Main loop
@@ -96,7 +94,7 @@
 
     // Wait for the queue to become non-empty
     G1StringDedupQueue::wait();
-    if (_should_terminate) {
+    if (should_terminate()) {
       break;
     }
 
@@ -133,23 +131,10 @@
     }
   }
 
-  terminate();
 }
 
-void G1StringDedupThread::stop() {
-  {
-    MonitorLockerEx ml(Terminator_lock);
-    _thread->_should_terminate = true;
-  }
-
+void G1StringDedupThread::stop_service() {
   G1StringDedupQueue::cancel_wait();
-
-  {
-    MonitorLockerEx ml(Terminator_lock);
-    while (!_thread->_has_terminated) {
-      ml.wait();
-    }
-  }
 }
 
 void G1StringDedupThread::print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
--- a/src/share/vm/gc/g1/g1StringDedupThread.hpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/g1StringDedupThread.hpp	Fri Mar 11 16:59:58 2016 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,14 +45,14 @@
 
   void print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
 
+  void run_service();
+  void stop_service();
+
 public:
   static void create();
-  static void stop();
 
   static G1StringDedupThread* thread();
 
-  virtual void run();
-
   void deduplicate_shared_strings(G1StringDedupStat& stat);
 };
 
--- a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -32,32 +32,6 @@
 #include "gc/g1/suspendibleThreadSet.hpp"
 #include "runtime/mutexLocker.hpp"
 
-void G1YoungRemSetSamplingThread::run() {
-  initialize_in_thread();
-  wait_for_universe_init();
-
-  run_service();
-
-  terminate();
-}
-
-void G1YoungRemSetSamplingThread::stop() {
-  // it is ok to take late safepoints here, if needed
-  {
-    MutexLockerEx mu(Terminator_lock);
-    _should_terminate = true;
-  }
-
-  stop_service();
-
-  {
-    MutexLockerEx mu(Terminator_lock);
-    while (!_has_terminated) {
-      Terminator_lock->wait();
-    }
-  }
-}
-
 G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() :
     ConcurrentGCThread(),
     _monitor(Mutex::nonleaf,
@@ -70,7 +44,7 @@
 
 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
   MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
-  if (!_should_terminate) {
+  if (!should_terminate()) {
     uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be?
     _monitor.wait(Mutex::_no_safepoint_check_flag, waitms);
   }
@@ -79,7 +53,7 @@
 void G1YoungRemSetSamplingThread::run_service() {
   double vtime_start = os::elapsedVTime();
 
-  while (!_should_terminate) {
+  while (!should_terminate()) {
     sample_young_list_rs_lengths();
 
     if (os::supports_vtime()) {
--- a/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp	Fri Mar 11 16:59:58 2016 -0500
@@ -55,9 +55,6 @@
 public:
   G1YoungRemSetSamplingThread();
   double vtime_accum() { return _vtime_accum; }
-
-  virtual void run();
-  void stop();
 };
 
 #endif // SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP
--- a/src/share/vm/gc/shared/concurrentGCThread.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/shared/concurrentGCThread.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -37,12 +37,12 @@
   _should_terminate(false), _has_terminated(false) {
 };
 
-void ConcurrentGCThread::create_and_start() {
+void ConcurrentGCThread::create_and_start(ThreadPriority prio) {
   if (os::create_thread(this, os::cgc_thread)) {
     // XXX: need to set this to low priority
     // unless "aggressive mode" set; priority
     // should be just less than that of VMThread.
-    os::set_priority(this, NearMaxPriority);
+    os::set_priority(this, prio);
     if (!_should_terminate && !DisableStartThread) {
       os::start_thread(this);
     }
@@ -75,6 +75,34 @@
   }
 }
 
+void ConcurrentGCThread::run() {
+  initialize_in_thread();
+  wait_for_universe_init();
+
+  run_service();
+
+  terminate();
+}
+
+void ConcurrentGCThread::stop() {
+  // it is ok to take late safepoints here, if needed
+  {
+    MutexLockerEx mu(Terminator_lock);
+    assert(!_has_terminated,   "stop should only be called once");
+    assert(!_should_terminate, "stop should only be called once");
+    _should_terminate = true;
+  }
+
+  stop_service();
+
+  {
+    MutexLockerEx mu(Terminator_lock);
+    while (!_has_terminated) {
+      Terminator_lock->wait();
+    }
+  }
+}
+
 static void _sltLoop(JavaThread* thread, TRAPS) {
   SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
   slt->loop();
--- a/src/share/vm/gc/shared/concurrentGCThread.hpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/shared/concurrentGCThread.hpp	Fri Mar 11 16:59:58 2016 -0500
@@ -31,13 +31,9 @@
 class ConcurrentGCThread: public NamedThread {
   friend class VMStructs;
 
-protected:
   bool volatile _should_terminate;
   bool _has_terminated;
 
-  // Create and start the thread (setting it's priority high.)
-  void create_and_start();
-
   // Do initialization steps in the thread: record stack base and size,
   // init thread local storage, set JNI handle block.
   void initialize_in_thread();
@@ -49,11 +45,29 @@
   // concurrent work.
   void terminate();
 
+protected:
+  // Create and start the thread (setting it's priority.)
+  void create_and_start(ThreadPriority prio = NearMaxPriority);
+
+  // Do the specific GC work. Called by run() after initialization complete.
+  virtual void run_service() = 0;
+
+  // Shut down the specific GC work. Called by stop() as part of termination protocol.
+  virtual void stop_service()  = 0;
+
 public:
   ConcurrentGCThread();
 
   // Tester
   bool is_ConcurrentGC_thread() const { return true; }
+
+  virtual void run();
+
+  // shutdown following termination protocol
+  virtual void stop();
+
+  bool should_terminate() { return _should_terminate; }
+  bool has_terminated()   { return _has_terminated; }
 };
 
 // The SurrogateLockerThread is used by concurrent GC threads for
--- a/src/share/vm/gc/shared/genCollectedHeap.cpp	Sun Mar 13 13:26:47 2016 +0100
+++ b/src/share/vm/gc/shared/genCollectedHeap.cpp	Fri Mar 11 16:59:58 2016 -0500
@@ -1281,7 +1281,7 @@
 void GenCollectedHeap::stop() {
 #if INCLUDE_ALL_GCS
   if (UseConcMarkSweepGC) {
-    ConcurrentMarkSweepThread::stop();
+    ConcurrentMarkSweepThread::cmst()->stop();
   }
 #endif
 }