提交 5ee7f6f4 编写于 作者: I iveresov

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
上级 221e50e3
......@@ -30,7 +30,7 @@ PtrQueue::PtrQueue(PtrQueueSet* qset_, bool perm) :
_perm(perm), _lock(NULL)
{}
PtrQueue::~PtrQueue() {
void PtrQueue::flush() {
if (!_perm && _buf != NULL) {
if (_index == _sz) {
// No work to do.
......@@ -41,8 +41,9 @@ PtrQueue::~PtrQueue() {
_buf[byte_index_to_index((int)i)] = NULL;
}
qset()->enqueue_complete_buffer(_buf);
_buf = NULL;
}
_buf = NULL;
_index = 0;
}
}
......
......@@ -62,7 +62,9 @@ public:
// given PtrQueueSet.
PtrQueue(PtrQueueSet*, bool perm = false);
// Release any contained resources.
~PtrQueue();
void flush();
// Calls flush() when destroyed.
~PtrQueue() { flush(); }
// Associate a lock with a ptr queue.
void set_lock(Mutex* lock) { _lock = lock; }
......
......@@ -1422,6 +1422,7 @@ static void ensure_join(JavaThread* thread) {
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 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
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 (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 (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 (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
}
if (UseTLAB) {
tlab().make_parsable(true); // retire TLAB, if any
}
#ifndef SERIALGC
if (UseG1GC) {
flush_barrier_queues();
}
#endif
Threads::remove(this);
delete this;
Threads::remove(this);
delete this;
}
JavaThread* JavaThread::active() {
Thread* thread = ThreadLocalStorage::thread();
assert(thread != NULL, "just checking");
......
......@@ -793,6 +793,8 @@ class JavaThread: public Thread {
DirtyCardQueue _dirty_card_queue; // Thread-local log for dirty cards.
// Set of all such queues.
static DirtyCardQueueSet _dirty_card_queue_set;
void flush_barrier_queues();
#endif // !SERIALGC
friend class VMThread;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册