7119584: UseParallelGC barrier task can be overwritten.
Summary: Provoke a GC for a metadata allocation failure.
Reviewed-by: johnc, iveresov
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Fri Dec 09 06:46:57 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Fri Dec 09 19:28:34 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,6 +53,9 @@
case noop_task:
result = "noop task";
break;
+ case idle_task:
+ result = "idle task";
+ break;
}
return result;
};
@@ -782,6 +785,12 @@
void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
list->enqueue(fin);
+ // The barrier task will be read by one of the GC
+ // workers once it is added to the list of tasks.
+ // Be sure that is globally visible before the
+ // GC worker reads it (which is after the task is added
+ // to the list of tasks below).
+ OrderAccess::storestore();
add_list(list);
fin->wait_for(true /* reset */);
// We have to release the barrier tasks!
@@ -833,11 +842,15 @@
IdleGCTask* IdleGCTask::create() {
IdleGCTask* result = new IdleGCTask(false);
+ assert(UseDynamicNumberOfGCThreads,
+ "Should only be used with dynamic GC thread");
return result;
}
IdleGCTask* IdleGCTask::create_on_c_heap() {
IdleGCTask* result = new(ResourceObj::C_HEAP) IdleGCTask(true);
+ assert(UseDynamicNumberOfGCThreads,
+ "Should only be used with dynamic GC thread");
return result;
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Fri Dec 09 06:46:57 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Fri Dec 09 19:28:34 2011 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -129,6 +129,8 @@
for (; /* break */; ) {
// This will block until there is a task to be gotten.
GCTask* task = manager()->get_task(which());
+ // Record if this is an idle task for later use.
+ bool is_idle_task = task->is_idle_task();
// In case the update is costly
if (PrintGCTaskTimeStamps) {
timer.update();
@@ -137,9 +139,13 @@
jlong entry_time = timer.ticks();
char* name = task->name();
+ // If this is the barrier task, it can be destroyed
+ // by the GC task manager once the do_it() executes.
task->do_it(manager(), which());
- if (!task->is_idle_task()) {
+ // Use the saved value of is_idle_task because references
+ // using "task" are not reliable for the barrier task.
+ if (!is_idle_task) {
manager()->note_completion(which());
if (PrintGCTaskTimeStamps) {