annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 10185:d50cc62e94ff

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