--- old/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp 2016-06-23 12:33:38.607511370 -0700 +++ new/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp 2016-06-23 12:33:38.515511373 -0700 @@ -2888,7 +2888,10 @@ CMSParInitialMarkTask tsk(this, &srs, n_workers); initialize_sequential_subtasks_for_young_gen_rescan(n_workers); - if (n_workers > 1) { + // If the total workers is greater than 1, then multiple workers + // may be used at some time and the initialization has been set + // such that the single threaded path cannot be used. + if (workers->total_workers() > 1) { workers->run_task(&tsk); } else { tsk.work(0); @@ -3507,7 +3510,7 @@ uint num_workers = AdaptiveSizePolicy::calc_active_conc_workers(conc_workers()->total_workers(), conc_workers()->active_workers(), Threads::number_of_non_daemon_threads()); - conc_workers()->set_active_workers(num_workers); + num_workers = conc_workers()->update_active_workers(num_workers); CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace(); --- old/src/share/vm/gc/cms/parNewGeneration.cpp 2016-06-23 12:33:39.227511348 -0700 +++ new/src/share/vm/gc/cms/parNewGeneration.cpp 2016-06-23 12:33:39.131511351 -0700 @@ -898,7 +898,7 @@ AdaptiveSizePolicy::calc_active_workers(workers->total_workers(), workers->active_workers(), Threads::number_of_non_daemon_threads()); - workers->set_active_workers(active_workers); + active_workers = workers->update_active_workers(active_workers); _old_gen = gch->old_gen(); // If the next generation is too full to accommodate worst-case promotion @@ -952,7 +952,9 @@ // separate thread causes wide variance in run times. We can't help this // in the multi-threaded case, but we special-case n=1 here to get // repeatable measurements of the 1-thread overhead of the parallel code. - if (active_workers > 1) { + // Might multiple workers ever be used? If yes, initialization + // has been done such that the single threaded path should not be used. + if (workers->total_workers() > 1) { workers->run_task(&tsk); } else { tsk.work(0); --- old/src/share/vm/gc/g1/g1CollectedHeap.cpp 2016-06-23 12:33:39.755511330 -0700 +++ new/src/share/vm/gc/g1/g1CollectedHeap.cpp 2016-06-23 12:33:39.663511333 -0700 @@ -1333,7 +1333,7 @@ AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), workers()->active_workers(), Threads::number_of_non_daemon_threads()); - workers()->set_active_workers(n_workers); + workers()->update_active_workers(n_workers); ParRebuildRSTask rebuild_rs_task(this); workers()->run_task(&rebuild_rs_task); @@ -3166,7 +3166,7 @@ uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), workers()->active_workers(), Threads::number_of_non_daemon_threads()); - workers()->set_active_workers(active_workers); + workers()->update_active_workers(active_workers); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); --- old/src/share/vm/gc/g1/g1ConcurrentMark.cpp 2016-06-23 12:33:40.307511310 -0700 +++ new/src/share/vm/gc/g1/g1ConcurrentMark.cpp 2016-06-23 12:33:40.207511314 -0700 @@ -1033,11 +1033,14 @@ uint active_workers = MAX2(1U, parallel_marking_threads()); assert(active_workers > 0, "Should have been set"); + // Setting active workers is not guaranteed since fewer + // worker threads may currently exist and more may not be + // available. + active_workers = _parallel_workers->update_active_workers(active_workers); // Parallel task terminator is set in "set_concurrency_and_phase()" set_concurrency_and_phase(active_workers, true /* concurrent */); G1CMConcurrentMarkingTask markingTask(this, cmThread()); - _parallel_workers->set_active_workers(active_workers); _parallel_workers->run_task(&markingTask); print_stats(); } --- old/src/share/vm/gc/parallel/gcTaskManager.cpp 2016-06-23 12:33:40.843511292 -0700 +++ new/src/share/vm/gc/parallel/gcTaskManager.cpp 2016-06-23 12:33:40.755511295 -0700 @@ -529,7 +529,7 @@ created_workers() - active_workers() - idle_workers(); if (more_inactive_workers < 0) { int reduced_active_workers = active_workers() + more_inactive_workers; - set_active_workers(reduced_active_workers); + update_active_workers(reduced_active_workers); more_inactive_workers = 0; } log_trace(gc, task)("JT: %d workers %d active %d idle %d more %d", --- old/src/share/vm/gc/parallel/gcTaskManager.hpp 2016-06-23 12:33:41.331511275 -0700 +++ new/src/share/vm/gc/parallel/gcTaskManager.hpp 2016-06-23 12:33:41.247511278 -0700 @@ -457,11 +457,12 @@ uint workers() const { return _workers; } - void set_active_workers(uint v) { + uint update_active_workers(uint v) { assert(v <= _workers, "Trying to set more workers active than there are"); _active_workers = MIN2(v, _workers); assert(v != 0, "Trying to set active workers to 0"); _active_workers = MAX2(1U, _active_workers); + return _active_workers; } // Sets the number of threads that will be used in a collection void set_active_gang(); --- old/src/share/vm/gc/parallel/psScavenge.cpp 2016-06-23 12:33:41.843511257 -0700 +++ new/src/share/vm/gc/parallel/psScavenge.cpp 2016-06-23 12:33:41.747511260 -0700 @@ -391,11 +391,15 @@ ParallelTaskTerminator terminator( active_workers, (TaskQueueSetSuper*) promotion_manager->stack_array_depth()); - if (active_workers > 1) { - for (uint j = 0; j < active_workers; j++) { - q->enqueue(new StealTask(&terminator)); + // If active_workers can exceed 1, add a StrealTask. + // PSPromotionManager::drain_stacks_depth() does not fully drain its + // stacks and expects a StealTask to complete the draining if + // ParallelGCThreads is > 1. + if (gc_task_manager()->workers() > 1) { + for (uint j = 0; j < active_workers; j++) { + q->enqueue(new StealTask(&terminator)); + } } - } gc_task_manager()->execute_and_wait(q); } --- old/src/share/vm/gc/shared/workgroup.cpp 2016-06-23 12:33:42.379511238 -0700 +++ new/src/share/vm/gc/shared/workgroup.cpp 2016-06-23 12:33:42.279511242 -0700 @@ -271,8 +271,11 @@ "Trying to execute task %s with %u workers which is more than the amount of total workers %u.", task->name(), num_workers, total_workers()); guarantee(num_workers > 0, "Trying to execute task %s with zero workers", task->name()); - add_workers(num_workers, false); - _dispatcher->coordinator_execute_on_workers(task, num_workers); + // num_workers may have been calculated based on different criteria + // than _active_workers so use num_workers limited by the number of + // created workers. + uint active_workers = MIN2(_created_workers, num_workers); + _dispatcher->coordinator_execute_on_workers(task, active_workers); } AbstractGangWorker::AbstractGangWorker(AbstractWorkGang* gang, uint id) { --- old/src/share/vm/gc/shared/workgroup.hpp 2016-06-23 12:33:42.859511221 -0700 +++ new/src/share/vm/gc/shared/workgroup.hpp 2016-06-23 12:33:42.763511225 -0700 @@ -156,7 +156,7 @@ return _active_workers; } - void set_active_workers(uint v) { + uint update_active_workers(uint v) { assert(v <= _total_workers, "Trying to set more workers active than there are"); _active_workers = MIN2(v, _total_workers); @@ -165,6 +165,7 @@ assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, "Unless dynamic should use total workers"); log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers); + return _active_workers; } // Add GC workers as needed. --- old/src/share/vm/runtime/globals.hpp 2016-06-23 12:33:43.367511204 -0700 +++ new/src/share/vm/runtime/globals.hpp 2016-06-23 12:33:43.271511207 -0700 @@ -1539,7 +1539,7 @@ "Dynamically choose the number of parallel threads " \ "parallel gc will use") \ \ - diagnostic(bool, InjectGCWorkerCreationFailure, false, \ + diagnostic(bool, InjectGCWorkerCreationFailure, false, \ "Inject thread creation failures for " \ "UseDynamicNumberOfGCThreads") \ \