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