comparison src/share/vm/utilities/yieldingWorkgroup.cpp @ 1833:8b10f48633dc

6984287: Regularize how GC parallel workers are specified. Summary: Associate number of GC workers with the workgang as opposed to the task. Reviewed-by: johnc, ysr
author jmasa
date Mon, 20 Sep 2010 14:38:38 -0700
parents c18cbe5936b8
children f95d63e2154a
comparison
equal deleted inserted replaced
1781:97fbf5beff7b 1833:8b10f48633dc
1 /* 1 /*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2005, 2010 Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
30 class GangWorker; 30 class GangWorker;
31 class WorkData; 31 class WorkData;
32 32
33 YieldingFlexibleWorkGang::YieldingFlexibleWorkGang( 33 YieldingFlexibleWorkGang::YieldingFlexibleWorkGang(
34 const char* name, int workers, bool are_GC_task_threads) : 34 const char* name, int workers, bool are_GC_task_threads) :
35 AbstractWorkGang(name, are_GC_task_threads, false) { 35 FlexibleWorkGang(name, workers, are_GC_task_threads, false),
36 // Save arguments. 36 _yielded_workers(0) {}
37 _total_workers = workers; 37
38 assert(_total_workers > 0, "Must have more than 1 worker"); 38 GangWorker* YieldingFlexibleWorkGang::allocate_worker(int which) {
39 39 YieldingFlexibleGangWorker* new_member =
40 _yielded_workers = 0; 40 new YieldingFlexibleGangWorker(this, which);
41 41 return (YieldingFlexibleGangWorker*) new_member;
42 if (TraceWorkGang) {
43 tty->print_cr("Constructing work gang %s with %d threads", name, workers);
44 }
45 _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, workers);
46 assert(gang_workers() != NULL, "Failed to allocate gang workers");
47 for (int worker = 0; worker < total_workers(); worker += 1) {
48 YieldingFlexibleGangWorker* new_worker =
49 new YieldingFlexibleGangWorker(this, worker);
50 assert(new_worker != NULL, "Failed to allocate YieldingFlexibleGangWorker");
51 _gang_workers[worker] = new_worker;
52 if (new_worker == NULL || !os::create_thread(new_worker, os::pgc_thread))
53 vm_exit_out_of_memory(0, "Cannot create worker GC thread. Out of system resources.");
54 if (!DisableStartThread) {
55 os::start_thread(new_worker);
56 }
57 }
58 } 42 }
59 43
60 // Run a task; returns when the task is done, or the workers yield, 44 // Run a task; returns when the task is done, or the workers yield,
61 // or the task is aborted, or the work gang is terminated via stop(). 45 // or the task is aborted, or the work gang is terminated via stop().
62 // A task that has been yielded can be continued via this interface 46 // A task that has been yielded can be continued via this interface
140 _active_workers = MIN2(requested_size, total_workers()); 124 _active_workers = MIN2(requested_size, total_workers());
141 } else { 125 } else {
142 _active_workers = total_workers(); 126 _active_workers = total_workers();
143 } 127 }
144 new_task->set_actual_size(_active_workers); 128 new_task->set_actual_size(_active_workers);
129 new_task->set_for_termination(_active_workers);
145 130
146 assert(_started_workers == 0, "Tabula rasa non"); 131 assert(_started_workers == 0, "Tabula rasa non");
147 assert(_finished_workers == 0, "Tabula rasa non"); 132 assert(_finished_workers == 0, "Tabula rasa non");
148 assert(_yielded_workers == 0, "Tabula rasa non"); 133 assert(_yielded_workers == 0, "Tabula rasa non");
149 yielding_task()->set_status(ACTIVE); 134 yielding_task()->set_status(ACTIVE);
159 assert(monitor()->owned_by_self(), "Data race"); 144 assert(monitor()->owned_by_self(), "Data race");
160 // Wait for task to complete or yield 145 // Wait for task to complete or yield
161 for (Status status = yielding_task()->status(); 146 for (Status status = yielding_task()->status();
162 status != COMPLETED && status != YIELDED && status != ABORTED; 147 status != COMPLETED && status != YIELDED && status != ABORTED;
163 status = yielding_task()->status()) { 148 status = yielding_task()->status()) {
164 assert(started_workers() <= active_workers(), "invariant"); 149 assert(started_workers() <= total_workers(), "invariant");
165 assert(finished_workers() <= active_workers(), "invariant"); 150 assert(finished_workers() <= total_workers(), "invariant");
166 assert(yielded_workers() <= active_workers(), "invariant"); 151 assert(yielded_workers() <= total_workers(), "invariant");
167 monitor()->wait(Mutex::_no_safepoint_check_flag); 152 monitor()->wait(Mutex::_no_safepoint_check_flag);
168 } 153 }
169 switch (yielding_task()->status()) { 154 switch (yielding_task()->status()) {
170 case COMPLETED: 155 case COMPLETED:
171 case ABORTED: { 156 case ABORTED: {
172 assert(finished_workers() == active_workers(), "Inconsistent status"); 157 assert(finished_workers() == total_workers(), "Inconsistent status");
173 assert(yielded_workers() == 0, "Invariant"); 158 assert(yielded_workers() == 0, "Invariant");
174 reset(); // for next task; gang<->task binding released 159 reset(); // for next task; gang<->task binding released
175 break; 160 break;
176 } 161 }
177 case YIELDED: { 162 case YIELDED: {
178 assert(yielded_workers() > 0, "Invariant"); 163 assert(yielded_workers() > 0, "Invariant");
179 assert(yielded_workers() + finished_workers() == active_workers(), 164 assert(yielded_workers() + finished_workers() == total_workers(),
180 "Inconsistent counts"); 165 "Inconsistent counts");
181 break; 166 break;
182 } 167 }
183 case ACTIVE: 168 case ACTIVE:
184 case INACTIVE: 169 case INACTIVE:
206 } 191 }
207 192
208 void YieldingFlexibleWorkGang::reset() { 193 void YieldingFlexibleWorkGang::reset() {
209 _started_workers = 0; 194 _started_workers = 0;
210 _finished_workers = 0; 195 _finished_workers = 0;
211 _active_workers = 0;
212 yielding_task()->set_gang(NULL); 196 yielding_task()->set_gang(NULL);
213 _task = NULL; // unbind gang from task 197 _task = NULL; // unbind gang from task
214 } 198 }
215 199
216 void YieldingFlexibleWorkGang::yield() { 200 void YieldingFlexibleWorkGang::yield() {
217 assert(task() != NULL, "Inconsistency; should have task binding"); 201 assert(task() != NULL, "Inconsistency; should have task binding");
218 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); 202 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
219 assert(yielded_workers() < active_workers(), "Consistency check"); 203 assert(yielded_workers() < total_workers(), "Consistency check");
220 if (yielding_task()->status() == ABORTING) { 204 if (yielding_task()->status() == ABORTING) {
221 // Do not yield; we need to abort as soon as possible 205 // Do not yield; we need to abort as soon as possible
222 // XXX NOTE: This can cause a performance pathology in the 206 // XXX NOTE: This can cause a performance pathology in the
223 // current implementation in Mustang, as of today, and 207 // current implementation in Mustang, as of today, and
224 // pre-Mustang in that as soon as an overflow occurs, 208 // pre-Mustang in that as soon as an overflow occurs,
225 // yields will not be honoured. The right way to proceed 209 // yields will not be honoured. The right way to proceed
226 // of course is to fix bug # TBF, so that abort's cause 210 // of course is to fix bug # TBF, so that abort's cause
227 // us to return at each potential yield point. 211 // us to return at each potential yield point.
228 return; 212 return;
229 } 213 }
230 if (++_yielded_workers + finished_workers() == active_workers()) { 214 if (++_yielded_workers + finished_workers() == total_workers()) {
231 yielding_task()->set_status(YIELDED); 215 yielding_task()->set_status(YIELDED);
232 monitor()->notify_all(); 216 monitor()->notify_all();
233 } else { 217 } else {
234 yielding_task()->set_status(YIELDING); 218 yielding_task()->set_status(YIELDING);
235 } 219 }