RFR (XS): ConcurrentMark overflow queues cleanup

Aleksey Shipilev shade at redhat.com
Tue Nov 8 21:46:58 UTC 2016


Hi,

So, during the debugging session we discovered the inconsistency between
ShenandoahConcurrentMark::concurrent_mark_loop and
ShenandoahConcurrentMark::cancel. The first one does not empty the
overflow queues on cancelled concgc, which may set them up for
processing on the next cycle! Oops.

Also, % _max_conc_worker_id is not safe if we want to maintain the
invariant that any given queue is only served by a single thread.

Fixes:

diff -r f0002694db11 src/share/vm/gc/shenandoah/shenandoahConcurrentMark.hpp
--- a/src/share/vm/gc/shenandoah/shenandoahConcurrentMark.hpp	Tue Nov 08
15:50:02 2016 +0100
+++ b/src/share/vm/gc/shenandoah/shenandoahConcurrentMark.hpp	Tue Nov 08
22:41:27 2016 +0100
@@ -145,6 +145,8 @@
   inline bool try_to_steal(uint worker_id, ShenandoahMarkObjsClosure<T,
CL>* cl, int *seed);

   SCMObjToScanQueue* get_queue(uint worker_id);
+  void clear_queue(SCMObjToScanQueue *q);
+
   inline bool try_draining_an_satb_buffer(SCMObjToScanQueue* q);
   void drain_satb_buffers(uint worker_id, bool remark = false);
   SCMObjToScanQueueSet* task_queues() { return _task_queues;}

diff -r f0002694db11 src/share/vm/gc/shenandoah/shenandoahConcurrentMark.cpp
--- a/src/share/vm/gc/shenandoah/shenandoahConcurrentMark.cpp	Tue Nov 08
15:50:02 2016 +0100
+++ b/src/share/vm/gc/shenandoah/shenandoahConcurrentMark.cpp	Tue Nov 08
22:45:47 2016 +0100
@@ -857,19 +857,24 @@
   // Clean up marking stacks.
   SCMObjToScanQueueSet* queues = task_queues();
   for (uint i = 0; i < _max_conc_worker_id; ++i) {
-    SCMObjToScanQueue* task_queue = queues->queue(i);
-    task_queue->set_empty();
-    task_queue->overflow_stack()->clear();
+    clear_queue(queues->queue(i));
   }

   // Cancel SATB buffers.
   JavaThread::satb_mark_queue_set().abandon_partial_marking();
 }
+
 SCMObjToScanQueue* ShenandoahConcurrentMark::get_queue(uint worker_id) {
-  worker_id = worker_id % _max_conc_worker_id;
+  assert (worker_id < _max_conc_worker_id, "valid worker id: %d",
worker_id);
   return _task_queues->queue(worker_id);
 }

+void ShenandoahConcurrentMark::clear_queue(SCMObjToScanQueue *q) {
+  q->set_empty();
+  q->overflow_stack()->clear();
+}
+
 template <class T, bool CL>
 void
ShenandoahConcurrentMark::concurrent_mark_loop(ShenandoahMarkObjsClosure<T,
CL>* cl,
                                                     uint worker_id,
@@ -878,7 +883,7 @@
   ShenandoahHeap* heap = ShenandoahHeap::heap();
   int seed = 17;
   while (true) {
-    if (heap->cancelled_concgc())  q->set_empty();
+    if (heap->cancelled_concgc()) clear_queue(q);
     if (heap->cancelled_concgc() ||
         (!try_queue(q, cl) &&

Good to go?

Thanks,
-Aleksey



More information about the shenandoah-dev mailing list