Mercurial > hg > graal-compiler
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 } |