RFR (XS): ConcurrentMark overflow queues cleanup

Roman Kennke rkennke at redhat.com
Tue Nov 8 23:23:41 UTC 2016


Yes, go!


Am Dienstag, den 08.11.2016, 22:46 +0100 schrieb Aleksey Shipilev:
> 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(ShenandoahMarkObjsClos
> ure<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