Mercurial > hg > truffle
diff src/share/vm/runtime/thread.cpp @ 441:da9cb4e97a5f
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
author | iveresov |
---|---|
date | Fri, 14 Nov 2008 14:23:05 -0800 |
parents | 99dd4bbd9eec |
children | eca19a8425b5 |
line wrap: on
line diff
--- a/src/share/vm/runtime/thread.cpp Fri Nov 07 12:52:16 2008 -0800 +++ b/src/share/vm/runtime/thread.cpp Fri Nov 14 14:23:05 2008 -0800 @@ -1422,6 +1422,7 @@ thread->clear_pending_exception(); } + // For any new cleanup additions, please check to see if they need to be applied to // cleanup_failed_attach_current_thread as well. void JavaThread::exit(bool destroy_vm, ExitType exit_type) { @@ -1592,39 +1593,62 @@ JvmtiExport::cleanup_thread(this); } +#ifndef SERIALGC + // We must flush G1-related buffers before removing a thread from + // the list of active threads. + if (UseG1GC) { + flush_barrier_queues(); + } +#endif + // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } +#ifndef SERIALGC +// Flush G1-related queues. +void JavaThread::flush_barrier_queues() { + satb_mark_queue().flush(); + dirty_card_queue().flush(); +} +#endif + void JavaThread::cleanup_failed_attach_current_thread() { - - if (get_thread_profiler() != NULL) { - get_thread_profiler()->disengage(); - ResourceMark rm; - get_thread_profiler()->print(get_thread_name()); - } - - if (active_handles() != NULL) { - JNIHandleBlock* block = active_handles(); - set_active_handles(NULL); - JNIHandleBlock::release_block(block); - } - - if (free_handle_block() != NULL) { - JNIHandleBlock* block = free_handle_block(); - set_free_handle_block(NULL); - JNIHandleBlock::release_block(block); - } - - if (UseTLAB) { - tlab().make_parsable(true); // retire TLAB, if any - } - - Threads::remove(this); - delete this; + if (get_thread_profiler() != NULL) { + get_thread_profiler()->disengage(); + ResourceMark rm; + get_thread_profiler()->print(get_thread_name()); + } + + if (active_handles() != NULL) { + JNIHandleBlock* block = active_handles(); + set_active_handles(NULL); + JNIHandleBlock::release_block(block); + } + + if (free_handle_block() != NULL) { + JNIHandleBlock* block = free_handle_block(); + set_free_handle_block(NULL); + JNIHandleBlock::release_block(block); + } + + if (UseTLAB) { + tlab().make_parsable(true); // retire TLAB, if any + } + +#ifndef SERIALGC + if (UseG1GC) { + flush_barrier_queues(); + } +#endif + + Threads::remove(this); + delete this; } + + JavaThread* JavaThread::active() { Thread* thread = ThreadLocalStorage::thread(); assert(thread != NULL, "just checking");