8079579: Add SuspendibleThreadSetLeaver and make SuspendibleThreadSet::joint()/leave() private
authorpliden
Mon, 11 May 2015 13:57:30 +0200 (2015-05-11)
changeset 30613 a7815bb05ae2
parent 30612 89fd070a30a3
child 30614 e45861098f5a
8079579: Add SuspendibleThreadSetLeaver and make SuspendibleThreadSet::joint()/leave() private Reviewed-by: brutisso, david
hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Mon May 11 10:29:57 2015 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Mon May 11 13:57:30 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -77,7 +77,7 @@
 }
 
 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
-  SuspendibleThreadSetJoiner sts;
+  SuspendibleThreadSetJoiner sts_join;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1p = g1h->g1_policy();
   if (g1p->adaptive_young_list_length()) {
@@ -89,8 +89,8 @@
 
       // we try to yield every time we visit 10 regions
       if (regions_visited == 10) {
-        if (sts.should_yield()) {
-          sts.yield();
+        if (sts_join.should_yield()) {
+          sts_join.yield();
           // we just abandon the iteration
           break;
         }
@@ -188,7 +188,7 @@
     }
 
     {
-      SuspendibleThreadSetJoiner sts;
+      SuspendibleThreadSetJoiner sts_join;
 
       do {
         int curr_buffer_num = (int)dcqs.completed_buffers_num();
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon May 11 10:29:57 2015 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon May 11 13:57:30 2015 +0200
@@ -193,13 +193,8 @@
       _cl(cl), _suspendible(suspendible), AbstractGangTask("Parallel Clear Bitmap Task"), _hrclaimer(n_workers) {}
 
   void work(uint worker_id) {
-    if (_suspendible) {
-      SuspendibleThreadSet::join();
-    }
+    SuspendibleThreadSetJoiner sts_join(_suspendible);
     G1CollectedHeap::heap()->heap_region_par_iterate(_cl, worker_id, &_hrclaimer, true);
-    if (_suspendible) {
-      SuspendibleThreadSet::leave();
-    }
   }
 };
 
@@ -956,19 +951,17 @@
  */
 
 void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
+  bool barrier_aborted;
+
   if (verbose_low()) {
     gclog_or_tty->print_cr("[%u] entering first barrier", worker_id);
   }
 
-  if (concurrent()) {
-    SuspendibleThreadSet::leave();
+  {
+    SuspendibleThreadSetLeaver sts_leave(concurrent());
+    barrier_aborted = !_first_overflow_barrier_sync.enter();
   }
 
-  bool barrier_aborted = !_first_overflow_barrier_sync.enter();
-
-  if (concurrent()) {
-    SuspendibleThreadSet::join();
-  }
   // at this point everyone should have synced up and not be doing any
   // more work
 
@@ -1015,19 +1008,17 @@
 }
 
 void ConcurrentMark::enter_second_sync_barrier(uint worker_id) {
+  bool barrier_aborted;
+
   if (verbose_low()) {
     gclog_or_tty->print_cr("[%u] entering second barrier", worker_id);
   }
 
-  if (concurrent()) {
-    SuspendibleThreadSet::leave();
+  {
+    SuspendibleThreadSetLeaver sts_leave(concurrent());
+    barrier_aborted = !_second_overflow_barrier_sync.enter();
   }
 
-  bool barrier_aborted = !_second_overflow_barrier_sync.enter();
-
-  if (concurrent()) {
-    SuspendibleThreadSet::join();
-  }
   // at this point everything should be re-initialized and ready to go
 
   if (verbose_low()) {
@@ -1078,40 +1069,41 @@
 
     double start_vtime = os::elapsedVTime();
 
-    SuspendibleThreadSet::join();
-
-    assert(worker_id < _cm->active_tasks(), "invariant");
-    CMTask* the_task = _cm->task(worker_id);
-    the_task->record_start_time();
-    if (!_cm->has_aborted()) {
-      do {
-        double start_vtime_sec = os::elapsedVTime();
-        double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
-
-        the_task->do_marking_step(mark_step_duration_ms,
-                                  true  /* do_termination */,
-                                  false /* is_serial*/);
-
-        double end_vtime_sec = os::elapsedVTime();
-        double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
-        _cm->clear_has_overflown();
-
-        _cm->do_yield_check(worker_id);
-
-        jlong sleep_time_ms;
-        if (!_cm->has_aborted() && the_task->has_aborted()) {
-          sleep_time_ms =
-            (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
-          SuspendibleThreadSet::leave();
-          os::sleep(Thread::current(), sleep_time_ms, false);
-          SuspendibleThreadSet::join();
-        }
-      } while (!_cm->has_aborted() && the_task->has_aborted());
+    {
+      SuspendibleThreadSetJoiner sts_join;
+
+      assert(worker_id < _cm->active_tasks(), "invariant");
+      CMTask* the_task = _cm->task(worker_id);
+      the_task->record_start_time();
+      if (!_cm->has_aborted()) {
+        do {
+          double start_vtime_sec = os::elapsedVTime();
+          double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
+
+          the_task->do_marking_step(mark_step_duration_ms,
+                                    true  /* do_termination */,
+                                    false /* is_serial*/);
+
+          double end_vtime_sec = os::elapsedVTime();
+          double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
+          _cm->clear_has_overflown();
+
+          _cm->do_yield_check(worker_id);
+
+          jlong sleep_time_ms;
+          if (!_cm->has_aborted() && the_task->has_aborted()) {
+            sleep_time_ms =
+              (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
+            {
+              SuspendibleThreadSetLeaver sts_leave;
+              os::sleep(Thread::current(), sleep_time_ms, false);
+            }
+          }
+        } while (!_cm->has_aborted() && the_task->has_aborted());
+      }
+      the_task->record_end_time();
+      guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
     }
-    the_task->record_end_time();
-    guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
-
-    SuspendibleThreadSet::leave();
 
     double end_vtime = os::elapsedVTime();
     _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Mon May 11 10:29:57 2015 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Mon May 11 13:57:30 2015 +0200
@@ -192,7 +192,7 @@
       } else {
         // We don't want to update the marking status if a GC pause
         // is already underway.
-        SuspendibleThreadSetJoiner sts;
+        SuspendibleThreadSetJoiner sts_join;
         g1h->set_marking_complete();
       }
 
@@ -262,7 +262,7 @@
       // not needed any more as the concurrent mark state has been
       // already reset).
       {
-        SuspendibleThreadSetJoiner sts;
+        SuspendibleThreadSetJoiner sts_join;
         if (!cm()->has_aborted()) {
           g1_policy->record_concurrent_mark_cleanup_completed();
         }
@@ -291,7 +291,7 @@
     // Java thread is waiting for a full GC to happen (e.g., it
     // called System.gc() with +ExplicitGCInvokesConcurrent).
     {
-      SuspendibleThreadSetJoiner sts;
+      SuspendibleThreadSetJoiner sts_join;
       g1h->increment_old_marking_cycles_completed(true /* concurrent */);
       g1h->register_concurrent_cycle_end();
     }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Mon May 11 10:29:57 2015 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Mon May 11 13:57:30 2015 +0200
@@ -74,7 +74,7 @@
 
     {
       // Include thread in safepoints
-      SuspendibleThreadSetJoiner sts;
+      SuspendibleThreadSetJoiner sts_join;
 
       stat.mark_exec();
 
@@ -88,9 +88,9 @@
         G1StringDedupTable::deduplicate(java_string, stat);
 
         // Safepoint this thread if needed
-        if (sts.should_yield()) {
+        if (sts_join.should_yield()) {
           stat.mark_block();
-          sts.yield();
+          sts_join.yield();
           stat.mark_unblock();
         }
       }
--- a/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp	Mon May 11 10:29:57 2015 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp	Mon May 11 13:57:30 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, 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
@@ -36,19 +36,22 @@
 // suspending thread later calls desynchronize(), allowing the suspended
 // threads to continue.
 class SuspendibleThreadSet : public AllStatic {
+  friend class SuspendibleThreadSetJoiner;
+  friend class SuspendibleThreadSetLeaver;
+
 private:
   static uint   _nthreads;
   static uint   _nthreads_stopped;
   static bool   _suspend_all;
   static double _suspend_all_start;
 
-public:
   // Add the current thread to the set. May block if a suspension is in progress.
   static void join();
 
   // Removes the current thread from the set.
   static void leave();
 
+public:
   // Returns true if an suspension is in progress.
   static bool should_yield() { return _suspend_all; }
 
@@ -63,22 +66,52 @@
 };
 
 class SuspendibleThreadSetJoiner : public StackObj {
+private:
+  bool _active;
+
 public:
-  SuspendibleThreadSetJoiner() {
-    SuspendibleThreadSet::join();
+  SuspendibleThreadSetJoiner(bool active = true) : _active(active) {
+    if (_active) {
+      SuspendibleThreadSet::join();
+    }
   }
 
   ~SuspendibleThreadSetJoiner() {
-    SuspendibleThreadSet::leave();
+    if (_active) {
+      SuspendibleThreadSet::leave();
+    }
   }
 
   bool should_yield() {
-    return SuspendibleThreadSet::should_yield();
+    if (_active) {
+      return SuspendibleThreadSet::should_yield();
+    } else {
+      return false;
+    }
   }
 
   void yield() {
+    assert(_active, "Thread has not joined the suspendible thread set");
     SuspendibleThreadSet::yield();
   }
 };
 
+class SuspendibleThreadSetLeaver : public StackObj {
+private:
+  bool _active;
+
+public:
+  SuspendibleThreadSetLeaver(bool active = true) : _active(active) {
+    if (_active) {
+      SuspendibleThreadSet::leave();
+    }
+  }
+
+  ~SuspendibleThreadSetLeaver() {
+    if (_active) {
+      SuspendibleThreadSet::join();
+    }
+  }
+};
+
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP