annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 20197:ce8f6bb717c9

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