7119584: UseParallelGC barrier task can be overwritten.
authorjmasa
Fri, 09 Dec 2011 19:28:34 -0800
changeset 11208 101816314520
parent 11207 07d48ddd8231
child 11210 6c8b4664d4ea
child 11247 d6faa02b3802
7119584: UseParallelGC barrier task can be overwritten. Summary: Provoke a GC for a metadata allocation failure. Reviewed-by: johnc, iveresov
hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp
hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp
--- 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) {