Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 4111:55d777c0860a
7118648: disable compressed oops by default on MacOS X until 7118647 is fixed
Summary: UseCompressedOops is false by default on MacOS X; can still be set manually
Reviewed-by: jmelvin, kvn, dholmes
author | dcubed |
---|---|
date | Wed, 07 Dec 2011 07:27:09 -0800 |
parents | bca17e38de00 |
children | 6d7d0790074d |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
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 | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" | |
27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp" | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
28 #include "gc_implementation/shared/adaptiveSizePolicy.hpp" |
1972 | 29 #include "memory/allocation.hpp" |
30 #include "memory/allocation.inline.hpp" | |
31 #include "runtime/mutex.hpp" | |
32 #include "runtime/mutexLocker.hpp" | |
0 | 33 |
34 // | |
35 // GCTask | |
36 // | |
37 | |
38 const char* GCTask::Kind::to_string(kind value) { | |
39 const char* result = "unknown GCTask kind"; | |
40 switch (value) { | |
41 default: | |
42 result = "unknown GCTask kind"; | |
43 break; | |
44 case unknown_task: | |
45 result = "unknown task"; | |
46 break; | |
47 case ordinary_task: | |
48 result = "ordinary task"; | |
49 break; | |
50 case barrier_task: | |
51 result = "barrier task"; | |
52 break; | |
53 case noop_task: | |
54 result = "noop task"; | |
55 break; | |
56 } | |
57 return result; | |
58 }; | |
59 | |
60 GCTask::GCTask() : | |
61 _kind(Kind::ordinary_task), | |
62 _affinity(GCTaskManager::sentinel_worker()){ | |
63 initialize(); | |
64 } | |
65 | |
66 GCTask::GCTask(Kind::kind kind) : | |
67 _kind(kind), | |
68 _affinity(GCTaskManager::sentinel_worker()) { | |
69 initialize(); | |
70 } | |
71 | |
72 GCTask::GCTask(uint affinity) : | |
73 _kind(Kind::ordinary_task), | |
74 _affinity(affinity) { | |
75 initialize(); | |
76 } | |
77 | |
78 GCTask::GCTask(Kind::kind kind, uint affinity) : | |
79 _kind(kind), | |
80 _affinity(affinity) { | |
81 initialize(); | |
82 } | |
83 | |
84 void GCTask::initialize() { | |
85 _older = NULL; | |
86 _newer = NULL; | |
87 } | |
88 | |
89 void GCTask::destruct() { | |
90 assert(older() == NULL, "shouldn't have an older task"); | |
91 assert(newer() == NULL, "shouldn't have a newer task"); | |
92 // Nothing to do. | |
93 } | |
94 | |
95 NOT_PRODUCT( | |
96 void GCTask::print(const char* message) const { | |
97 tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT, | |
98 newer(), this, affinity(), older()); | |
99 } | |
100 ) | |
101 | |
102 // | |
103 // GCTaskQueue | |
104 // | |
105 | |
106 GCTaskQueue* GCTaskQueue::create() { | |
107 GCTaskQueue* result = new GCTaskQueue(false); | |
108 if (TraceGCTaskQueue) { | |
109 tty->print_cr("GCTaskQueue::create()" | |
110 " returns " INTPTR_FORMAT, result); | |
111 } | |
112 return result; | |
113 } | |
114 | |
115 GCTaskQueue* GCTaskQueue::create_on_c_heap() { | |
116 GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true); | |
117 if (TraceGCTaskQueue) { | |
118 tty->print_cr("GCTaskQueue::create_on_c_heap()" | |
119 " returns " INTPTR_FORMAT, | |
120 result); | |
121 } | |
122 return result; | |
123 } | |
124 | |
125 GCTaskQueue::GCTaskQueue(bool on_c_heap) : | |
126 _is_c_heap_obj(on_c_heap) { | |
127 initialize(); | |
128 if (TraceGCTaskQueue) { | |
129 tty->print_cr("[" INTPTR_FORMAT "]" | |
130 " GCTaskQueue::GCTaskQueue() constructor", | |
131 this); | |
132 } | |
133 } | |
134 | |
135 void GCTaskQueue::destruct() { | |
136 // Nothing to do. | |
137 } | |
138 | |
139 void GCTaskQueue::destroy(GCTaskQueue* that) { | |
140 if (TraceGCTaskQueue) { | |
141 tty->print_cr("[" INTPTR_FORMAT "]" | |
142 " GCTaskQueue::destroy()" | |
143 " is_c_heap_obj: %s", | |
144 that, | |
145 that->is_c_heap_obj() ? "true" : "false"); | |
146 } | |
147 // That instance may have been allocated as a CHeapObj, | |
148 // in which case we have to free it explicitly. | |
149 if (that != NULL) { | |
150 that->destruct(); | |
151 assert(that->is_empty(), "should be empty"); | |
152 if (that->is_c_heap_obj()) { | |
153 FreeHeap(that); | |
154 } | |
155 } | |
156 } | |
157 | |
158 void GCTaskQueue::initialize() { | |
159 set_insert_end(NULL); | |
160 set_remove_end(NULL); | |
161 set_length(0); | |
162 } | |
163 | |
164 // Enqueue one task. | |
165 void GCTaskQueue::enqueue(GCTask* task) { | |
166 if (TraceGCTaskQueue) { | |
167 tty->print_cr("[" INTPTR_FORMAT "]" | |
168 " GCTaskQueue::enqueue(task: " | |
169 INTPTR_FORMAT ")", | |
170 this, task); | |
171 print("before:"); | |
172 } | |
173 assert(task != NULL, "shouldn't have null task"); | |
174 assert(task->older() == NULL, "shouldn't be on queue"); | |
175 assert(task->newer() == NULL, "shouldn't be on queue"); | |
176 task->set_newer(NULL); | |
177 task->set_older(insert_end()); | |
178 if (is_empty()) { | |
179 set_remove_end(task); | |
180 } else { | |
181 insert_end()->set_newer(task); | |
182 } | |
183 set_insert_end(task); | |
184 increment_length(); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
185 verify_length(); |
0 | 186 if (TraceGCTaskQueue) { |
187 print("after:"); | |
188 } | |
189 } | |
190 | |
191 // Enqueue a whole list of tasks. Empties the argument list. | |
192 void GCTaskQueue::enqueue(GCTaskQueue* list) { | |
193 if (TraceGCTaskQueue) { | |
194 tty->print_cr("[" INTPTR_FORMAT "]" | |
195 " GCTaskQueue::enqueue(list: " | |
196 INTPTR_FORMAT ")", | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
197 this, list); |
0 | 198 print("before:"); |
199 list->print("list:"); | |
200 } | |
201 if (list->is_empty()) { | |
202 // Enqueuing the empty list: nothing to do. | |
203 return; | |
204 } | |
205 uint list_length = list->length(); | |
206 if (is_empty()) { | |
207 // Enqueuing to empty list: just acquire elements. | |
208 set_insert_end(list->insert_end()); | |
209 set_remove_end(list->remove_end()); | |
210 set_length(list_length); | |
211 } else { | |
212 // Prepend argument list to our queue. | |
213 list->remove_end()->set_older(insert_end()); | |
214 insert_end()->set_newer(list->remove_end()); | |
215 set_insert_end(list->insert_end()); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
216 set_length(length() + list_length); |
0 | 217 // empty the argument list. |
218 } | |
219 list->initialize(); | |
220 if (TraceGCTaskQueue) { | |
221 print("after:"); | |
222 list->print("list:"); | |
223 } | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
224 verify_length(); |
0 | 225 } |
226 | |
227 // Dequeue one task. | |
228 GCTask* GCTaskQueue::dequeue() { | |
229 if (TraceGCTaskQueue) { | |
230 tty->print_cr("[" INTPTR_FORMAT "]" | |
231 " GCTaskQueue::dequeue()", this); | |
232 print("before:"); | |
233 } | |
234 assert(!is_empty(), "shouldn't dequeue from empty list"); | |
235 GCTask* result = remove(); | |
236 assert(result != NULL, "shouldn't have NULL task"); | |
237 if (TraceGCTaskQueue) { | |
238 tty->print_cr(" return: " INTPTR_FORMAT, result); | |
239 print("after:"); | |
240 } | |
241 return result; | |
242 } | |
243 | |
244 // Dequeue one task, preferring one with affinity. | |
245 GCTask* GCTaskQueue::dequeue(uint affinity) { | |
246 if (TraceGCTaskQueue) { | |
247 tty->print_cr("[" INTPTR_FORMAT "]" | |
248 " GCTaskQueue::dequeue(%u)", this, affinity); | |
249 print("before:"); | |
250 } | |
251 assert(!is_empty(), "shouldn't dequeue from empty list"); | |
252 // Look down to the next barrier for a task with this affinity. | |
253 GCTask* result = NULL; | |
254 for (GCTask* element = remove_end(); | |
255 element != NULL; | |
256 element = element->newer()) { | |
257 if (element->is_barrier_task()) { | |
258 // Don't consider barrier tasks, nor past them. | |
259 result = NULL; | |
260 break; | |
261 } | |
262 if (element->affinity() == affinity) { | |
263 result = remove(element); | |
264 break; | |
265 } | |
266 } | |
267 // If we didn't find anything with affinity, just take the next task. | |
268 if (result == NULL) { | |
269 result = remove(); | |
270 } | |
271 if (TraceGCTaskQueue) { | |
272 tty->print_cr(" return: " INTPTR_FORMAT, result); | |
273 print("after:"); | |
274 } | |
275 return result; | |
276 } | |
277 | |
278 GCTask* GCTaskQueue::remove() { | |
279 // Dequeue from remove end. | |
280 GCTask* result = remove_end(); | |
281 assert(result != NULL, "shouldn't have null task"); | |
282 assert(result->older() == NULL, "not the remove_end"); | |
283 set_remove_end(result->newer()); | |
284 if (remove_end() == NULL) { | |
285 assert(insert_end() == result, "not a singleton"); | |
286 set_insert_end(NULL); | |
287 } else { | |
288 remove_end()->set_older(NULL); | |
289 } | |
290 result->set_newer(NULL); | |
291 decrement_length(); | |
292 assert(result->newer() == NULL, "shouldn't be on queue"); | |
293 assert(result->older() == NULL, "shouldn't be on queue"); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
294 verify_length(); |
0 | 295 return result; |
296 } | |
297 | |
298 GCTask* GCTaskQueue::remove(GCTask* task) { | |
299 // This is slightly more work, and has slightly fewer asserts | |
300 // than removing from the remove end. | |
301 assert(task != NULL, "shouldn't have null task"); | |
302 GCTask* result = task; | |
303 if (result->newer() != NULL) { | |
304 result->newer()->set_older(result->older()); | |
305 } else { | |
306 assert(insert_end() == result, "not youngest"); | |
307 set_insert_end(result->older()); | |
308 } | |
309 if (result->older() != NULL) { | |
310 result->older()->set_newer(result->newer()); | |
311 } else { | |
312 assert(remove_end() == result, "not oldest"); | |
313 set_remove_end(result->newer()); | |
314 } | |
315 result->set_newer(NULL); | |
316 result->set_older(NULL); | |
317 decrement_length(); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
318 verify_length(); |
0 | 319 return result; |
320 } | |
321 | |
322 NOT_PRODUCT( | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
323 // Count the elements in the queue and verify the length against |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
324 // that count. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
325 void GCTaskQueue::verify_length() const { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
326 uint count = 0; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
327 for (GCTask* element = insert_end(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
328 element != NULL; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
329 element = element->older()) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
330 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
331 count++; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
332 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
333 assert(count == length(), "Length does not match queue"); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
334 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
335 |
0 | 336 void GCTaskQueue::print(const char* message) const { |
337 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:" | |
338 " insert_end: " INTPTR_FORMAT | |
339 " remove_end: " INTPTR_FORMAT | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
340 " length: %d" |
0 | 341 " %s", |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
342 this, insert_end(), remove_end(), length(), message); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
343 uint count = 0; |
0 | 344 for (GCTask* element = insert_end(); |
345 element != NULL; | |
346 element = element->older()) { | |
347 element->print(" "); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
348 count++; |
0 | 349 tty->cr(); |
350 } | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
351 tty->print("Total tasks: %d", count); |
0 | 352 } |
353 ) | |
354 | |
355 // | |
356 // SynchronizedGCTaskQueue | |
357 // | |
358 | |
359 SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg, | |
360 Monitor * lock_arg) : | |
361 _unsynchronized_queue(queue_arg), | |
362 _lock(lock_arg) { | |
363 assert(unsynchronized_queue() != NULL, "null queue"); | |
364 assert(lock() != NULL, "null lock"); | |
365 } | |
366 | |
367 SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() { | |
368 // Nothing to do. | |
369 } | |
370 | |
371 // | |
372 // GCTaskManager | |
373 // | |
374 GCTaskManager::GCTaskManager(uint workers) : | |
375 _workers(workers), | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
376 _active_workers(0), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
377 _idle_workers(0), |
0 | 378 _ndc(NULL) { |
379 initialize(); | |
380 } | |
381 | |
382 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) : | |
383 _workers(workers), | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
384 _active_workers(0), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
385 _idle_workers(0), |
0 | 386 _ndc(ndc) { |
387 initialize(); | |
388 } | |
389 | |
390 void GCTaskManager::initialize() { | |
391 if (TraceGCTaskManager) { | |
392 tty->print_cr("GCTaskManager::initialize: workers: %u", workers()); | |
393 } | |
394 assert(workers() != 0, "no workers"); | |
395 _monitor = new Monitor(Mutex::barrier, // rank | |
396 "GCTaskManager monitor", // name | |
397 Mutex::_allow_vm_block_flag); // allow_vm_block | |
398 // The queue for the GCTaskManager must be a CHeapObj. | |
399 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); | |
400 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); | |
401 _noop_task = NoopGCTask::create_on_c_heap(); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
402 _idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap(); |
0 | 403 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers()); |
404 { | |
405 // Set up worker threads. | |
406 // Distribute the workers among the available processors, | |
407 // unless we were told not to, or if the os doesn't want to. | |
408 uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers()); | |
409 if (!BindGCTaskThreadsToCPUs || | |
410 !os::distribute_processes(workers(), processor_assignment)) { | |
411 for (uint a = 0; a < workers(); a += 1) { | |
412 processor_assignment[a] = sentinel_worker(); | |
413 } | |
414 } | |
415 _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers()); | |
416 for (uint t = 0; t < workers(); t += 1) { | |
417 set_thread(t, GCTaskThread::create(this, t, processor_assignment[t])); | |
418 } | |
419 if (TraceGCTaskThread) { | |
420 tty->print("GCTaskManager::initialize: distribution:"); | |
421 for (uint t = 0; t < workers(); t += 1) { | |
422 tty->print(" %u", processor_assignment[t]); | |
423 } | |
424 tty->cr(); | |
425 } | |
426 FREE_C_HEAP_ARRAY(uint, processor_assignment); | |
427 } | |
428 reset_busy_workers(); | |
429 set_unblocked(); | |
430 for (uint w = 0; w < workers(); w += 1) { | |
431 set_resource_flag(w, false); | |
432 } | |
433 reset_delivered_tasks(); | |
434 reset_completed_tasks(); | |
435 reset_noop_tasks(); | |
436 reset_barriers(); | |
437 reset_emptied_queue(); | |
438 for (uint s = 0; s < workers(); s += 1) { | |
439 thread(s)->start(); | |
440 } | |
441 } | |
442 | |
443 GCTaskManager::~GCTaskManager() { | |
444 assert(busy_workers() == 0, "still have busy workers"); | |
445 assert(queue()->is_empty(), "still have queued work"); | |
446 NoopGCTask::destroy(_noop_task); | |
447 _noop_task = NULL; | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
448 WaitForBarrierGCTask::destroy(_idle_inactive_task); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
449 _idle_inactive_task = NULL; |
0 | 450 if (_thread != NULL) { |
451 for (uint i = 0; i < workers(); i += 1) { | |
452 GCTaskThread::destroy(thread(i)); | |
453 set_thread(i, NULL); | |
454 } | |
455 FREE_C_HEAP_ARRAY(GCTaskThread*, _thread); | |
456 _thread = NULL; | |
457 } | |
458 if (_resource_flag != NULL) { | |
459 FREE_C_HEAP_ARRAY(bool, _resource_flag); | |
460 _resource_flag = NULL; | |
461 } | |
462 if (queue() != NULL) { | |
463 GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue(); | |
464 GCTaskQueue::destroy(unsynchronized_queue); | |
465 SynchronizedGCTaskQueue::destroy(queue()); | |
466 _queue = NULL; | |
467 } | |
468 if (monitor() != NULL) { | |
469 delete monitor(); | |
470 _monitor = NULL; | |
471 } | |
472 } | |
473 | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
474 void GCTaskManager::set_active_gang() { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
475 _active_workers = |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
476 AdaptiveSizePolicy::calc_active_workers(workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
477 active_workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
478 Threads::number_of_non_daemon_threads()); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
479 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
480 assert(!all_workers_active() || active_workers() == ParallelGCThreads, |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
481 err_msg("all_workers_active() is incorrect: " |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
482 "active %d ParallelGCThreads %d", active_workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
483 ParallelGCThreads)); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
484 if (TraceDynamicGCThreads) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
485 gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): " |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
486 "all_workers_active() %d workers %d " |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
487 "active %d ParallelGCThreads %d ", |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
488 all_workers_active(), workers(), active_workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
489 ParallelGCThreads); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
490 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
491 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
492 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
493 // Create IdleGCTasks for inactive workers. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
494 // Creates tasks in a ResourceArea and assumes |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
495 // an appropriate ResourceMark. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
496 void GCTaskManager::task_idle_workers() { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
497 { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
498 int more_inactive_workers = 0; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
499 { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
500 // Stop any idle tasks from exiting their IdleGCTask's |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
501 // and get the count for additional IdleGCTask's under |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
502 // the GCTaskManager's monitor so that the "more_inactive_workers" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
503 // count is correct. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
504 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
505 _idle_inactive_task->set_should_wait(true); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
506 // active_workers are a number being requested. idle_workers |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
507 // are the number currently idle. If all the workers are being |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
508 // requested to be active but some are already idle, reduce |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
509 // the number of active_workers to be consistent with the |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
510 // number of idle_workers. The idle_workers are stuck in |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
511 // idle tasks and will no longer be release (since a new GC |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
512 // is starting). Try later to release enough idle_workers |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
513 // to allow the desired number of active_workers. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
514 more_inactive_workers = |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
515 workers() - active_workers() - idle_workers(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
516 if (more_inactive_workers < 0) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
517 int reduced_active_workers = active_workers() + more_inactive_workers; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
518 set_active_workers(reduced_active_workers); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
519 more_inactive_workers = 0; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
520 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
521 if (TraceDynamicGCThreads) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
522 gclog_or_tty->print_cr("JT: %d workers %d active %d " |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
523 "idle %d more %d", |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
524 Threads::number_of_non_daemon_threads(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
525 workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
526 active_workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
527 idle_workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
528 more_inactive_workers); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
529 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
530 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
531 GCTaskQueue* q = GCTaskQueue::create(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
532 for(uint i = 0; i < (uint) more_inactive_workers; i++) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
533 q->enqueue(IdleGCTask::create_on_c_heap()); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
534 increment_idle_workers(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
535 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
536 assert(workers() == active_workers() + idle_workers(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
537 "total workers should equal active + inactive"); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
538 add_list(q); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
539 // GCTaskQueue* q was created in a ResourceArea so a |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
540 // destroy() call is not needed. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
541 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
542 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
543 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
544 void GCTaskManager::release_idle_workers() { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
545 { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
546 MutexLockerEx ml(monitor(), |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
547 Mutex::_no_safepoint_check_flag); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
548 _idle_inactive_task->set_should_wait(false); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
549 monitor()->notify_all(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
550 // Release monitor |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
551 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
552 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
553 |
0 | 554 void GCTaskManager::print_task_time_stamps() { |
555 for(uint i=0; i<ParallelGCThreads; i++) { | |
556 GCTaskThread* t = thread(i); | |
557 t->print_task_time_stamps(); | |
558 } | |
559 } | |
560 | |
561 void GCTaskManager::print_threads_on(outputStream* st) { | |
562 uint num_thr = workers(); | |
563 for (uint i = 0; i < num_thr; i++) { | |
564 thread(i)->print_on(st); | |
565 st->cr(); | |
566 } | |
567 } | |
568 | |
569 void GCTaskManager::threads_do(ThreadClosure* tc) { | |
570 assert(tc != NULL, "Null ThreadClosure"); | |
571 uint num_thr = workers(); | |
572 for (uint i = 0; i < num_thr; i++) { | |
573 tc->do_thread(thread(i)); | |
574 } | |
575 } | |
576 | |
577 GCTaskThread* GCTaskManager::thread(uint which) { | |
578 assert(which < workers(), "index out of bounds"); | |
579 assert(_thread[which] != NULL, "shouldn't have null thread"); | |
580 return _thread[which]; | |
581 } | |
582 | |
583 void GCTaskManager::set_thread(uint which, GCTaskThread* value) { | |
584 assert(which < workers(), "index out of bounds"); | |
585 assert(value != NULL, "shouldn't have null thread"); | |
586 _thread[which] = value; | |
587 } | |
588 | |
589 void GCTaskManager::add_task(GCTask* task) { | |
590 assert(task != NULL, "shouldn't have null task"); | |
591 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
592 if (TraceGCTaskManager) { | |
593 tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])", | |
594 task, GCTask::Kind::to_string(task->kind())); | |
595 } | |
596 queue()->enqueue(task); | |
597 // Notify with the lock held to avoid missed notifies. | |
598 if (TraceGCTaskManager) { | |
599 tty->print_cr(" GCTaskManager::add_task (%s)->notify_all", | |
600 monitor()->name()); | |
601 } | |
602 (void) monitor()->notify_all(); | |
603 // Release monitor(). | |
604 } | |
605 | |
606 void GCTaskManager::add_list(GCTaskQueue* list) { | |
607 assert(list != NULL, "shouldn't have null task"); | |
608 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
609 if (TraceGCTaskManager) { | |
610 tty->print_cr("GCTaskManager::add_list(%u)", list->length()); | |
611 } | |
612 queue()->enqueue(list); | |
613 // Notify with the lock held to avoid missed notifies. | |
614 if (TraceGCTaskManager) { | |
615 tty->print_cr(" GCTaskManager::add_list (%s)->notify_all", | |
616 monitor()->name()); | |
617 } | |
618 (void) monitor()->notify_all(); | |
619 // Release monitor(). | |
620 } | |
621 | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
622 // GC workers wait in get_task() for new work to be added |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
623 // to the GCTaskManager's queue. When new work is added, |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
624 // a notify is sent to the waiting GC workers which then |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
625 // compete to get tasks. If a GC worker wakes up and there |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
626 // is no work on the queue, it is given a noop_task to execute |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
627 // and then loops to find more work. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
628 |
0 | 629 GCTask* GCTaskManager::get_task(uint which) { |
630 GCTask* result = NULL; | |
631 // Grab the queue lock. | |
632 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
633 // Wait while the queue is block or | |
634 // there is nothing to do, except maybe release resources. | |
635 while (is_blocked() || | |
636 (queue()->is_empty() && !should_release_resources(which))) { | |
637 if (TraceGCTaskManager) { | |
638 tty->print_cr("GCTaskManager::get_task(%u)" | |
639 " blocked: %s" | |
640 " empty: %s" | |
641 " release: %s", | |
642 which, | |
643 is_blocked() ? "true" : "false", | |
644 queue()->is_empty() ? "true" : "false", | |
645 should_release_resources(which) ? "true" : "false"); | |
646 tty->print_cr(" => (%s)->wait()", | |
647 monitor()->name()); | |
648 } | |
649 monitor()->wait(Mutex::_no_safepoint_check_flag, 0); | |
650 } | |
651 // We've reacquired the queue lock here. | |
652 // Figure out which condition caused us to exit the loop above. | |
653 if (!queue()->is_empty()) { | |
654 if (UseGCTaskAffinity) { | |
655 result = queue()->dequeue(which); | |
656 } else { | |
657 result = queue()->dequeue(); | |
658 } | |
659 if (result->is_barrier_task()) { | |
660 assert(which != sentinel_worker(), | |
661 "blocker shouldn't be bogus"); | |
662 set_blocking_worker(which); | |
663 } | |
664 } else { | |
665 // The queue is empty, but we were woken up. | |
666 // Just hand back a Noop task, | |
667 // in case someone wanted us to release resources, or whatever. | |
668 result = noop_task(); | |
669 increment_noop_tasks(); | |
670 } | |
671 assert(result != NULL, "shouldn't have null task"); | |
672 if (TraceGCTaskManager) { | |
673 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]", | |
674 which, result, GCTask::Kind::to_string(result->kind())); | |
675 tty->print_cr(" %s", result->name()); | |
676 } | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
677 if (!result->is_idle_task()) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
678 increment_busy_workers(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
679 increment_delivered_tasks(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
680 } |
0 | 681 return result; |
682 // Release monitor(). | |
683 } | |
684 | |
685 void GCTaskManager::note_completion(uint which) { | |
686 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
687 if (TraceGCTaskManager) { | |
688 tty->print_cr("GCTaskManager::note_completion(%u)", which); | |
689 } | |
690 // If we are blocked, check if the completing thread is the blocker. | |
691 if (blocking_worker() == which) { | |
692 assert(blocking_worker() != sentinel_worker(), | |
693 "blocker shouldn't be bogus"); | |
694 increment_barriers(); | |
695 set_unblocked(); | |
696 } | |
697 increment_completed_tasks(); | |
698 uint active = decrement_busy_workers(); | |
699 if ((active == 0) && (queue()->is_empty())) { | |
700 increment_emptied_queue(); | |
701 if (TraceGCTaskManager) { | |
702 tty->print_cr(" GCTaskManager::note_completion(%u) done", which); | |
703 } | |
704 // Notify client that we are done. | |
705 NotifyDoneClosure* ndc = notify_done_closure(); | |
706 if (ndc != NULL) { | |
707 ndc->notify(this); | |
708 } | |
709 } | |
710 if (TraceGCTaskManager) { | |
711 tty->print_cr(" GCTaskManager::note_completion(%u) (%s)->notify_all", | |
712 which, monitor()->name()); | |
713 tty->print_cr(" " | |
714 " blocked: %s" | |
715 " empty: %s" | |
716 " release: %s", | |
717 is_blocked() ? "true" : "false", | |
718 queue()->is_empty() ? "true" : "false", | |
719 should_release_resources(which) ? "true" : "false"); | |
720 tty->print_cr(" " | |
721 " delivered: %u" | |
722 " completed: %u" | |
723 " barriers: %u" | |
724 " emptied: %u", | |
725 delivered_tasks(), | |
726 completed_tasks(), | |
727 barriers(), | |
728 emptied_queue()); | |
729 } | |
730 // Tell everyone that a task has completed. | |
731 (void) monitor()->notify_all(); | |
732 // Release monitor(). | |
733 } | |
734 | |
735 uint GCTaskManager::increment_busy_workers() { | |
736 assert(queue()->own_lock(), "don't own the lock"); | |
737 _busy_workers += 1; | |
738 return _busy_workers; | |
739 } | |
740 | |
741 uint GCTaskManager::decrement_busy_workers() { | |
742 assert(queue()->own_lock(), "don't own the lock"); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
743 assert(_busy_workers > 0, "About to make a mistake"); |
0 | 744 _busy_workers -= 1; |
745 return _busy_workers; | |
746 } | |
747 | |
748 void GCTaskManager::release_all_resources() { | |
749 // If you want this to be done atomically, do it in a BarrierGCTask. | |
750 for (uint i = 0; i < workers(); i += 1) { | |
751 set_resource_flag(i, true); | |
752 } | |
753 } | |
754 | |
755 bool GCTaskManager::should_release_resources(uint which) { | |
756 // This can be done without a lock because each thread reads one element. | |
757 return resource_flag(which); | |
758 } | |
759 | |
760 void GCTaskManager::note_release(uint which) { | |
761 // This can be done without a lock because each thread writes one element. | |
762 set_resource_flag(which, false); | |
763 } | |
764 | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
765 // "list" contains tasks that are ready to execute. Those |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
766 // tasks are added to the GCTaskManager's queue of tasks and |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
767 // then the GC workers are notified that there is new work to |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
768 // do. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
769 // |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
770 // Typically different types of tasks can be added to the "list". |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
771 // For example in PSScavenge OldToYoungRootsTask, SerialOldToYoungRootsTask, |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
772 // ScavengeRootsTask, and StealTask tasks are all added to the list |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
773 // and then the GC workers are notified of new work. The tasks are |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
774 // handed out in the order in which they are added to the list |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
775 // (although execution is not necessarily in that order). As long |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
776 // as any tasks are running the GCTaskManager will wait for execution |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
777 // to complete. GC workers that execute a stealing task remain in |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
778 // the stealing task until all stealing tasks have completed. The load |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
779 // balancing afforded by the stealing tasks work best if the stealing |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
780 // tasks are added last to the list. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
781 |
0 | 782 void GCTaskManager::execute_and_wait(GCTaskQueue* list) { |
783 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create(); | |
784 list->enqueue(fin); | |
785 add_list(list); | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
786 fin->wait_for(true /* reset */); |
0 | 787 // We have to release the barrier tasks! |
788 WaitForBarrierGCTask::destroy(fin); | |
789 } | |
790 | |
791 bool GCTaskManager::resource_flag(uint which) { | |
792 assert(which < workers(), "index out of bounds"); | |
793 return _resource_flag[which]; | |
794 } | |
795 | |
796 void GCTaskManager::set_resource_flag(uint which, bool value) { | |
797 assert(which < workers(), "index out of bounds"); | |
798 _resource_flag[which] = value; | |
799 } | |
800 | |
801 // | |
802 // NoopGCTask | |
803 // | |
804 | |
805 NoopGCTask* NoopGCTask::create() { | |
806 NoopGCTask* result = new NoopGCTask(false); | |
807 return result; | |
808 } | |
809 | |
810 NoopGCTask* NoopGCTask::create_on_c_heap() { | |
811 NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true); | |
812 return result; | |
813 } | |
814 | |
815 void NoopGCTask::destroy(NoopGCTask* that) { | |
816 if (that != NULL) { | |
817 that->destruct(); | |
818 if (that->is_c_heap_obj()) { | |
819 FreeHeap(that); | |
820 } | |
821 } | |
822 } | |
823 | |
824 void NoopGCTask::destruct() { | |
825 // This has to know it's superclass structure, just like the constructor. | |
826 this->GCTask::destruct(); | |
827 // Nothing else to do. | |
828 } | |
829 | |
830 // | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
831 // IdleGCTask |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
832 // |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
833 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
834 IdleGCTask* IdleGCTask::create() { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
835 IdleGCTask* result = new IdleGCTask(false); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
836 return result; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
837 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
838 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
839 IdleGCTask* IdleGCTask::create_on_c_heap() { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
840 IdleGCTask* result = new(ResourceObj::C_HEAP) IdleGCTask(true); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
841 return result; |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
842 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
843 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
844 void IdleGCTask::do_it(GCTaskManager* manager, uint which) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
845 WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
846 if (TraceGCTaskManager) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
847 tty->print_cr("[" INTPTR_FORMAT "]" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
848 " IdleGCTask:::do_it()" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
849 " should_wait: %s", |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
850 this, wait_for_task->should_wait() ? "true" : "false"); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
851 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
852 MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
853 if (TraceDynamicGCThreads) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
854 gclog_or_tty->print_cr("--- idle %d", which); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
855 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
856 // Increment has to be done when the idle tasks are created. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
857 // manager->increment_idle_workers(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
858 manager->monitor()->notify_all(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
859 while (wait_for_task->should_wait()) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
860 if (TraceGCTaskManager) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
861 tty->print_cr("[" INTPTR_FORMAT "]" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
862 " IdleGCTask::do_it()" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
863 " [" INTPTR_FORMAT "] (%s)->wait()", |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
864 this, manager->monitor(), manager->monitor()->name()); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
865 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
866 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
867 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
868 manager->decrement_idle_workers(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
869 if (TraceDynamicGCThreads) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
870 gclog_or_tty->print_cr("--- release %d", which); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
871 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
872 if (TraceGCTaskManager) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
873 tty->print_cr("[" INTPTR_FORMAT "]" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
874 " IdleGCTask::do_it() returns" |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
875 " should_wait: %s", |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
876 this, wait_for_task->should_wait() ? "true" : "false"); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
877 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
878 // Release monitor(). |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
879 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
880 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
881 void IdleGCTask::destroy(IdleGCTask* that) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
882 if (that != NULL) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
883 that->destruct(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
884 if (that->is_c_heap_obj()) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
885 FreeHeap(that); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
886 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
887 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
888 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
889 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
890 void IdleGCTask::destruct() { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
891 // This has to know it's superclass structure, just like the constructor. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
892 this->GCTask::destruct(); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
893 // Nothing else to do. |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
894 } |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
895 |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
896 // |
0 | 897 // BarrierGCTask |
898 // | |
899 | |
900 void BarrierGCTask::do_it(GCTaskManager* manager, uint which) { | |
901 // Wait for this to be the only busy worker. | |
902 // ??? I thought of having a StackObj class | |
903 // whose constructor would grab the lock and come to the barrier, | |
904 // and whose destructor would release the lock, | |
905 // but that seems like too much mechanism for two lines of code. | |
906 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); | |
907 do_it_internal(manager, which); | |
908 // Release manager->lock(). | |
909 } | |
910 | |
911 void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) { | |
912 // Wait for this to be the only busy worker. | |
913 assert(manager->monitor()->owned_by_self(), "don't own the lock"); | |
914 assert(manager->is_blocked(), "manager isn't blocked"); | |
915 while (manager->busy_workers() > 1) { | |
916 if (TraceGCTaskManager) { | |
917 tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers", | |
918 which, manager->busy_workers()); | |
919 } | |
920 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0); | |
921 } | |
922 } | |
923 | |
924 void BarrierGCTask::destruct() { | |
925 this->GCTask::destruct(); | |
926 // Nothing else to do. | |
927 } | |
928 | |
929 // | |
930 // ReleasingBarrierGCTask | |
931 // | |
932 | |
933 void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) { | |
934 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); | |
935 do_it_internal(manager, which); | |
936 manager->release_all_resources(); | |
937 // Release manager->lock(). | |
938 } | |
939 | |
940 void ReleasingBarrierGCTask::destruct() { | |
941 this->BarrierGCTask::destruct(); | |
942 // Nothing else to do. | |
943 } | |
944 | |
945 // | |
946 // NotifyingBarrierGCTask | |
947 // | |
948 | |
949 void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) { | |
950 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); | |
951 do_it_internal(manager, which); | |
952 NotifyDoneClosure* ndc = notify_done_closure(); | |
953 if (ndc != NULL) { | |
954 ndc->notify(manager); | |
955 } | |
956 // Release manager->lock(). | |
957 } | |
958 | |
959 void NotifyingBarrierGCTask::destruct() { | |
960 this->BarrierGCTask::destruct(); | |
961 // Nothing else to do. | |
962 } | |
963 | |
964 // | |
965 // WaitForBarrierGCTask | |
966 // | |
967 WaitForBarrierGCTask* WaitForBarrierGCTask::create() { | |
968 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); | |
969 return result; | |
970 } | |
971 | |
972 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
973 WaitForBarrierGCTask* result = |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
974 new (ResourceObj::C_HEAP) WaitForBarrierGCTask(true); |
0 | 975 return result; |
976 } | |
977 | |
978 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) : | |
979 _is_c_heap_obj(on_c_heap) { | |
980 _monitor = MonitorSupply::reserve(); | |
981 set_should_wait(true); | |
982 if (TraceGCTaskManager) { | |
983 tty->print_cr("[" INTPTR_FORMAT "]" | |
984 " WaitForBarrierGCTask::WaitForBarrierGCTask()" | |
985 " monitor: " INTPTR_FORMAT, | |
986 this, monitor()); | |
987 } | |
988 } | |
989 | |
990 void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) { | |
991 if (that != NULL) { | |
992 if (TraceGCTaskManager) { | |
993 tty->print_cr("[" INTPTR_FORMAT "]" | |
994 " WaitForBarrierGCTask::destroy()" | |
995 " is_c_heap_obj: %s" | |
996 " monitor: " INTPTR_FORMAT, | |
997 that, | |
998 that->is_c_heap_obj() ? "true" : "false", | |
999 that->monitor()); | |
1000 } | |
1001 that->destruct(); | |
1002 if (that->is_c_heap_obj()) { | |
1003 FreeHeap(that); | |
1004 } | |
1005 } | |
1006 } | |
1007 | |
1008 void WaitForBarrierGCTask::destruct() { | |
1009 assert(monitor() != NULL, "monitor should not be NULL"); | |
1010 if (TraceGCTaskManager) { | |
1011 tty->print_cr("[" INTPTR_FORMAT "]" | |
1012 " WaitForBarrierGCTask::destruct()" | |
1013 " monitor: " INTPTR_FORMAT, | |
1014 this, monitor()); | |
1015 } | |
1016 this->BarrierGCTask::destruct(); | |
1017 // Clean up that should be in the destructor, | |
1018 // except that ResourceMarks don't call destructors. | |
1019 if (monitor() != NULL) { | |
1020 MonitorSupply::release(monitor()); | |
1021 } | |
1022 _monitor = (Monitor*) 0xDEAD000F; | |
1023 } | |
1024 | |
1025 void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) { | |
1026 if (TraceGCTaskManager) { | |
1027 tty->print_cr("[" INTPTR_FORMAT "]" | |
1028 " WaitForBarrierGCTask::do_it() waiting for idle" | |
1029 " monitor: " INTPTR_FORMAT, | |
1030 this, monitor()); | |
1031 } | |
1032 { | |
1033 // First, wait for the barrier to arrive. | |
1034 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag); | |
1035 do_it_internal(manager, which); | |
1036 // Release manager->lock(). | |
1037 } | |
1038 { | |
1039 // Then notify the waiter. | |
1040 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
1041 set_should_wait(false); | |
1042 // Waiter doesn't miss the notify in the wait_for method | |
1043 // since it checks the flag after grabbing the monitor. | |
1044 if (TraceGCTaskManager) { | |
1045 tty->print_cr("[" INTPTR_FORMAT "]" | |
1046 " WaitForBarrierGCTask::do_it()" | |
1047 " [" INTPTR_FORMAT "] (%s)->notify_all()", | |
1048 this, monitor(), monitor()->name()); | |
1049 } | |
1050 monitor()->notify_all(); | |
1051 // Release monitor(). | |
1052 } | |
1053 } | |
1054 | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
1055 void WaitForBarrierGCTask::wait_for(bool reset) { |
0 | 1056 if (TraceGCTaskManager) { |
1057 tty->print_cr("[" INTPTR_FORMAT "]" | |
1058 " WaitForBarrierGCTask::wait_for()" | |
1059 " should_wait: %s", | |
1060 this, should_wait() ? "true" : "false"); | |
1061 } | |
1062 { | |
1063 // Grab the lock and check again. | |
1064 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); | |
1065 while (should_wait()) { | |
1066 if (TraceGCTaskManager) { | |
1067 tty->print_cr("[" INTPTR_FORMAT "]" | |
1068 " WaitForBarrierGCTask::wait_for()" | |
1069 " [" INTPTR_FORMAT "] (%s)->wait()", | |
1070 this, monitor(), monitor()->name()); | |
1071 } | |
1072 monitor()->wait(Mutex::_no_safepoint_check_flag, 0); | |
1073 } | |
1074 // Reset the flag in case someone reuses this task. | |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
1075 if (reset) { |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
1076 set_should_wait(true); |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
1972
diff
changeset
|
1077 } |
0 | 1078 if (TraceGCTaskManager) { |
1079 tty->print_cr("[" INTPTR_FORMAT "]" | |
1080 " WaitForBarrierGCTask::wait_for() returns" | |
1081 " should_wait: %s", | |
1082 this, should_wait() ? "true" : "false"); | |
1083 } | |
1084 // Release monitor(). | |
1085 } | |
1086 } | |
1087 | |
1088 Mutex* MonitorSupply::_lock = NULL; | |
1089 GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL; | |
1090 | |
1091 Monitor* MonitorSupply::reserve() { | |
1092 Monitor* result = NULL; | |
1093 // Lazy initialization: possible race. | |
1094 if (lock() == NULL) { | |
1095 _lock = new Mutex(Mutex::barrier, // rank | |
1096 "MonitorSupply mutex", // name | |
1097 Mutex::_allow_vm_block_flag); // allow_vm_block | |
1098 } | |
1099 { | |
1100 MutexLockerEx ml(lock()); | |
1101 // Lazy initialization. | |
1102 if (freelist() == NULL) { | |
1103 _freelist = | |
1104 new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads, | |
1105 true); | |
1106 } | |
1107 if (! freelist()->is_empty()) { | |
1108 result = freelist()->pop(); | |
1109 } else { | |
1110 result = new Monitor(Mutex::barrier, // rank | |
1111 "MonitorSupply monitor", // name | |
1112 Mutex::_allow_vm_block_flag); // allow_vm_block | |
1113 } | |
1114 guarantee(result != NULL, "shouldn't return NULL"); | |
1115 assert(!result->is_locked(), "shouldn't be locked"); | |
1116 // release lock(). | |
1117 } | |
1118 return result; | |
1119 } | |
1120 | |
1121 void MonitorSupply::release(Monitor* instance) { | |
1122 assert(instance != NULL, "shouldn't release NULL"); | |
1123 assert(!instance->is_locked(), "shouldn't be locked"); | |
1124 { | |
1125 MutexLockerEx ml(lock()); | |
1126 freelist()->push(instance); | |
1127 // release lock(). | |
1128 } | |
1129 } |