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