6770608: G1: Mutator thread can flush barrier and satb queues during safepoint

Fri, 14 Nov 2008 14:23:05 -0800

author
iveresov
date
Fri, 14 Nov 2008 14:23:05 -0800
changeset 876
da9cb4e97a5f
parent 875
96c6da8f095c
child 877
8fa025608ec6

6770608: G1: Mutator thread can flush barrier and satb queues during safepoint
6660573: G1: BigApps Failure : guarantee(satb_mq_set.completed_buffers_num() == 0,"invariant")
Summary: When exiting a mutator thread is removed from the thread list before it has a chance to flush its SATB and barrier queues. If GC happens at this moment the objects that are refererred from these queues can be moved, which will case a crash. The fix is simply to flush the buffers before removing a thread from the list.
Reviewed-by: jcoomes, tonyp

src/share/vm/gc_implementation/g1/ptrQueue.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/ptrQueue.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Fri Nov 07 12:52:16 2008 -0800
     1.2 +++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Fri Nov 14 14:23:05 2008 -0800
     1.3 @@ -30,7 +30,7 @@
     1.4    _perm(perm), _lock(NULL)
     1.5  {}
     1.6  
     1.7 -PtrQueue::~PtrQueue() {
     1.8 +void PtrQueue::flush() {
     1.9    if (!_perm && _buf != NULL) {
    1.10      if (_index == _sz) {
    1.11        // No work to do.
    1.12 @@ -41,8 +41,9 @@
    1.13          _buf[byte_index_to_index((int)i)] = NULL;
    1.14        }
    1.15        qset()->enqueue_complete_buffer(_buf);
    1.16 -      _buf = NULL;
    1.17      }
    1.18 +    _buf = NULL;
    1.19 +    _index = 0;
    1.20    }
    1.21  }
    1.22  
     2.1 --- a/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Fri Nov 07 12:52:16 2008 -0800
     2.2 +++ b/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Fri Nov 14 14:23:05 2008 -0800
     2.3 @@ -62,7 +62,9 @@
     2.4    // given PtrQueueSet.
     2.5    PtrQueue(PtrQueueSet*, bool perm = false);
     2.6    // Release any contained resources.
     2.7 -  ~PtrQueue();
     2.8 +  void flush();
     2.9 +  // Calls flush() when destroyed.
    2.10 +  ~PtrQueue() { flush(); }
    2.11  
    2.12    // Associate a lock with a ptr queue.
    2.13    void set_lock(Mutex* lock) { _lock = lock; }
     3.1 --- a/src/share/vm/runtime/thread.cpp	Fri Nov 07 12:52:16 2008 -0800
     3.2 +++ b/src/share/vm/runtime/thread.cpp	Fri Nov 14 14:23:05 2008 -0800
     3.3 @@ -1422,6 +1422,7 @@
     3.4    thread->clear_pending_exception();
     3.5  }
     3.6  
     3.7 +
     3.8  // For any new cleanup additions, please check to see if they need to be applied to
     3.9  // cleanup_failed_attach_current_thread as well.
    3.10  void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
    3.11 @@ -1592,39 +1593,62 @@
    3.12      JvmtiExport::cleanup_thread(this);
    3.13    }
    3.14  
    3.15 +#ifndef SERIALGC
    3.16 +  // We must flush G1-related buffers before removing a thread from
    3.17 +  // the list of active threads.
    3.18 +  if (UseG1GC) {
    3.19 +    flush_barrier_queues();
    3.20 +  }
    3.21 +#endif
    3.22 +
    3.23    // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
    3.24    Threads::remove(this);
    3.25  }
    3.26  
    3.27 +#ifndef SERIALGC
    3.28 +// Flush G1-related queues.
    3.29 +void JavaThread::flush_barrier_queues() {
    3.30 +  satb_mark_queue().flush();
    3.31 +  dirty_card_queue().flush();
    3.32 +}
    3.33 +#endif
    3.34 +
    3.35  void JavaThread::cleanup_failed_attach_current_thread() {
    3.36 -
    3.37 -     if (get_thread_profiler() != NULL) {
    3.38 -       get_thread_profiler()->disengage();
    3.39 -       ResourceMark rm;
    3.40 -       get_thread_profiler()->print(get_thread_name());
    3.41 -     }
    3.42 -
    3.43 -     if (active_handles() != NULL) {
    3.44 -      JNIHandleBlock* block = active_handles();
    3.45 -      set_active_handles(NULL);
    3.46 -      JNIHandleBlock::release_block(block);
    3.47 -     }
    3.48 -
    3.49 -     if (free_handle_block() != NULL) {
    3.50 -       JNIHandleBlock* block = free_handle_block();
    3.51 -       set_free_handle_block(NULL);
    3.52 -       JNIHandleBlock::release_block(block);
    3.53 -     }
    3.54 -
    3.55 -     if (UseTLAB) {
    3.56 -       tlab().make_parsable(true);  // retire TLAB, if any
    3.57 -     }
    3.58 -
    3.59 -     Threads::remove(this);
    3.60 -     delete this;
    3.61 +  if (get_thread_profiler() != NULL) {
    3.62 +    get_thread_profiler()->disengage();
    3.63 +    ResourceMark rm;
    3.64 +    get_thread_profiler()->print(get_thread_name());
    3.65 +  }
    3.66 +
    3.67 +  if (active_handles() != NULL) {
    3.68 +    JNIHandleBlock* block = active_handles();
    3.69 +    set_active_handles(NULL);
    3.70 +    JNIHandleBlock::release_block(block);
    3.71 +  }
    3.72 +
    3.73 +  if (free_handle_block() != NULL) {
    3.74 +    JNIHandleBlock* block = free_handle_block();
    3.75 +    set_free_handle_block(NULL);
    3.76 +    JNIHandleBlock::release_block(block);
    3.77 +  }
    3.78 +
    3.79 +  if (UseTLAB) {
    3.80 +    tlab().make_parsable(true);  // retire TLAB, if any
    3.81 +  }
    3.82 +
    3.83 +#ifndef SERIALGC
    3.84 +  if (UseG1GC) {
    3.85 +    flush_barrier_queues();
    3.86 +  }
    3.87 +#endif
    3.88 +
    3.89 +  Threads::remove(this);
    3.90 +  delete this;
    3.91  }
    3.92  
    3.93  
    3.94 +
    3.95 +
    3.96  JavaThread* JavaThread::active() {
    3.97    Thread* thread = ThreadLocalStorage::thread();
    3.98    assert(thread != NULL, "just checking");
     4.1 --- a/src/share/vm/runtime/thread.hpp	Fri Nov 07 12:52:16 2008 -0800
     4.2 +++ b/src/share/vm/runtime/thread.hpp	Fri Nov 14 14:23:05 2008 -0800
     4.3 @@ -793,6 +793,8 @@
     4.4    DirtyCardQueue _dirty_card_queue;      // Thread-local log for dirty cards.
     4.5    // Set of all such queues.
     4.6    static DirtyCardQueueSet _dirty_card_queue_set;
     4.7 +
     4.8 +  void flush_barrier_queues();
     4.9  #endif // !SERIALGC
    4.10  
    4.11    friend class VMThread;

mercurial