Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 10185:d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
Summary: In graphKit INT operations were generated to access PtrQueue::_index which has type size_t. This is 64 bit on 64-bit machines. No problems occur on little endian machines as long as the index fits into 32 bit, but on big endian machines the upper part is read, which is zero. This leads to unnecessary branches to the slow path in the runtime.
Reviewed-by: twisti, johnc
Contributed-by: Martin Doerr <martin.doerr@sap.com>
author | johnc |
---|---|
date | Wed, 24 Apr 2013 14:48:43 -0700 |
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 } |