annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
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 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include "incls/_gcTaskManager.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 //
a61af66fc99e Initial load
duke
parents:
diff changeset
29 // GCTask
a61af66fc99e Initial load
duke
parents:
diff changeset
30 //
a61af66fc99e Initial load
duke
parents:
diff changeset
31
a61af66fc99e Initial load
duke
parents:
diff changeset
32 const char* GCTask::Kind::to_string(kind value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
33 const char* result = "unknown GCTask kind";
a61af66fc99e Initial load
duke
parents:
diff changeset
34 switch (value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
35 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
36 result = "unknown GCTask kind";
a61af66fc99e Initial load
duke
parents:
diff changeset
37 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
38 case unknown_task:
a61af66fc99e Initial load
duke
parents:
diff changeset
39 result = "unknown task";
a61af66fc99e Initial load
duke
parents:
diff changeset
40 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
41 case ordinary_task:
a61af66fc99e Initial load
duke
parents:
diff changeset
42 result = "ordinary task";
a61af66fc99e Initial load
duke
parents:
diff changeset
43 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
44 case barrier_task:
a61af66fc99e Initial load
duke
parents:
diff changeset
45 result = "barrier task";
a61af66fc99e Initial load
duke
parents:
diff changeset
46 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
47 case noop_task:
a61af66fc99e Initial load
duke
parents:
diff changeset
48 result = "noop task";
a61af66fc99e Initial load
duke
parents:
diff changeset
49 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 }
a61af66fc99e Initial load
duke
parents:
diff changeset
51 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
52 };
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 GCTask::GCTask() :
a61af66fc99e Initial load
duke
parents:
diff changeset
55 _kind(Kind::ordinary_task),
a61af66fc99e Initial load
duke
parents:
diff changeset
56 _affinity(GCTaskManager::sentinel_worker()){
a61af66fc99e Initial load
duke
parents:
diff changeset
57 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
58 }
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60 GCTask::GCTask(Kind::kind kind) :
a61af66fc99e Initial load
duke
parents:
diff changeset
61 _kind(kind),
a61af66fc99e Initial load
duke
parents:
diff changeset
62 _affinity(GCTaskManager::sentinel_worker()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
64 }
a61af66fc99e Initial load
duke
parents:
diff changeset
65
a61af66fc99e Initial load
duke
parents:
diff changeset
66 GCTask::GCTask(uint affinity) :
a61af66fc99e Initial load
duke
parents:
diff changeset
67 _kind(Kind::ordinary_task),
a61af66fc99e Initial load
duke
parents:
diff changeset
68 _affinity(affinity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
69 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
70 }
a61af66fc99e Initial load
duke
parents:
diff changeset
71
a61af66fc99e Initial load
duke
parents:
diff changeset
72 GCTask::GCTask(Kind::kind kind, uint affinity) :
a61af66fc99e Initial load
duke
parents:
diff changeset
73 _kind(kind),
a61af66fc99e Initial load
duke
parents:
diff changeset
74 _affinity(affinity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
75 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
76 }
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 void GCTask::initialize() {
a61af66fc99e Initial load
duke
parents:
diff changeset
79 _older = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
80 _newer = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
81 }
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83 void GCTask::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 assert(older() == NULL, "shouldn't have an older task");
a61af66fc99e Initial load
duke
parents:
diff changeset
85 assert(newer() == NULL, "shouldn't have a newer task");
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // Nothing to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
87 }
a61af66fc99e Initial load
duke
parents:
diff changeset
88
a61af66fc99e Initial load
duke
parents:
diff changeset
89 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
90 void GCTask::print(const char* message) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
91 tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
92 newer(), this, affinity(), older());
a61af66fc99e Initial load
duke
parents:
diff changeset
93 }
a61af66fc99e Initial load
duke
parents:
diff changeset
94 )
a61af66fc99e Initial load
duke
parents:
diff changeset
95
a61af66fc99e Initial load
duke
parents:
diff changeset
96 //
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // GCTaskQueue
a61af66fc99e Initial load
duke
parents:
diff changeset
98 //
a61af66fc99e Initial load
duke
parents:
diff changeset
99
a61af66fc99e Initial load
duke
parents:
diff changeset
100 GCTaskQueue* GCTaskQueue::create() {
a61af66fc99e Initial load
duke
parents:
diff changeset
101 GCTaskQueue* result = new GCTaskQueue(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
102 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
103 tty->print_cr("GCTaskQueue::create()"
a61af66fc99e Initial load
duke
parents:
diff changeset
104 " returns " INTPTR_FORMAT, result);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
106 return result;
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_on_c_heap() {
a61af66fc99e Initial load
duke
parents:
diff changeset
110 GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
111 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
112 tty->print_cr("GCTaskQueue::create_on_c_heap()"
a61af66fc99e Initial load
duke
parents:
diff changeset
113 " returns " INTPTR_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
114 result);
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 }
a61af66fc99e Initial load
duke
parents:
diff changeset
118
a61af66fc99e Initial load
duke
parents:
diff changeset
119 GCTaskQueue::GCTaskQueue(bool on_c_heap) :
a61af66fc99e Initial load
duke
parents:
diff changeset
120 _is_c_heap_obj(on_c_heap) {
a61af66fc99e Initial load
duke
parents:
diff changeset
121 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
122 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
124 " GCTaskQueue::GCTaskQueue() constructor",
a61af66fc99e Initial load
duke
parents:
diff changeset
125 this);
a61af66fc99e Initial load
duke
parents:
diff changeset
126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 void GCTaskQueue::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // Nothing to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
132
a61af66fc99e Initial load
duke
parents:
diff changeset
133 void GCTaskQueue::destroy(GCTaskQueue* that) {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
136 " GCTaskQueue::destroy()"
a61af66fc99e Initial load
duke
parents:
diff changeset
137 " is_c_heap_obj: %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
138 that,
a61af66fc99e Initial load
duke
parents:
diff changeset
139 that->is_c_heap_obj() ? "true" : "false");
a61af66fc99e Initial load
duke
parents:
diff changeset
140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
141 // That instance may have been allocated as a CHeapObj,
a61af66fc99e Initial load
duke
parents:
diff changeset
142 // in which case we have to free it explicitly.
a61af66fc99e Initial load
duke
parents:
diff changeset
143 if (that != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
144 that->destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
145 assert(that->is_empty(), "should be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
146 if (that->is_c_heap_obj()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 FreeHeap(that);
a61af66fc99e Initial load
duke
parents:
diff changeset
148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
151
a61af66fc99e Initial load
duke
parents:
diff changeset
152 void GCTaskQueue::initialize() {
a61af66fc99e Initial load
duke
parents:
diff changeset
153 set_insert_end(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
154 set_remove_end(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
155 set_length(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // Enqueue one task.
a61af66fc99e Initial load
duke
parents:
diff changeset
159 void GCTaskQueue::enqueue(GCTask* task) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
162 " GCTaskQueue::enqueue(task: "
a61af66fc99e Initial load
duke
parents:
diff changeset
163 INTPTR_FORMAT ")",
a61af66fc99e Initial load
duke
parents:
diff changeset
164 this, task);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 print("before:");
a61af66fc99e Initial load
duke
parents:
diff changeset
166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
167 assert(task != NULL, "shouldn't have null task");
a61af66fc99e Initial load
duke
parents:
diff changeset
168 assert(task->older() == NULL, "shouldn't be on queue");
a61af66fc99e Initial load
duke
parents:
diff changeset
169 assert(task->newer() == NULL, "shouldn't be on queue");
a61af66fc99e Initial load
duke
parents:
diff changeset
170 task->set_newer(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
171 task->set_older(insert_end());
a61af66fc99e Initial load
duke
parents:
diff changeset
172 if (is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 set_remove_end(task);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 insert_end()->set_newer(task);
a61af66fc99e Initial load
duke
parents:
diff changeset
176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
177 set_insert_end(task);
a61af66fc99e Initial load
duke
parents:
diff changeset
178 increment_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
179 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
180 print("after:");
a61af66fc99e Initial load
duke
parents:
diff changeset
181 }
a61af66fc99e Initial load
duke
parents:
diff changeset
182 }
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // Enqueue a whole list of tasks. Empties the argument list.
a61af66fc99e Initial load
duke
parents:
diff changeset
185 void GCTaskQueue::enqueue(GCTaskQueue* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
187 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
188 " GCTaskQueue::enqueue(list: "
a61af66fc99e Initial load
duke
parents:
diff changeset
189 INTPTR_FORMAT ")",
a61af66fc99e Initial load
duke
parents:
diff changeset
190 this);
a61af66fc99e Initial load
duke
parents:
diff changeset
191 print("before:");
a61af66fc99e Initial load
duke
parents:
diff changeset
192 list->print("list:");
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194 if (list->is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
195 // Enqueuing the empty list: nothing to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
196 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
198 uint list_length = list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
199 if (is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
200 // Enqueuing to empty list: just acquire elements.
a61af66fc99e Initial load
duke
parents:
diff changeset
201 set_insert_end(list->insert_end());
a61af66fc99e Initial load
duke
parents:
diff changeset
202 set_remove_end(list->remove_end());
a61af66fc99e Initial load
duke
parents:
diff changeset
203 set_length(list_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
204 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // Prepend argument list to our queue.
a61af66fc99e Initial load
duke
parents:
diff changeset
206 list->remove_end()->set_older(insert_end());
a61af66fc99e Initial load
duke
parents:
diff changeset
207 insert_end()->set_newer(list->remove_end());
a61af66fc99e Initial load
duke
parents:
diff changeset
208 set_insert_end(list->insert_end());
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // empty the argument list.
a61af66fc99e Initial load
duke
parents:
diff changeset
210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
211 set_length(length() + list_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 list->initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
213 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
214 print("after:");
a61af66fc99e Initial load
duke
parents:
diff changeset
215 list->print("list:");
a61af66fc99e Initial load
duke
parents:
diff changeset
216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
218
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // Dequeue one task.
a61af66fc99e Initial load
duke
parents:
diff changeset
220 GCTask* GCTaskQueue::dequeue() {
a61af66fc99e Initial load
duke
parents:
diff changeset
221 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
222 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
223 " GCTaskQueue::dequeue()", this);
a61af66fc99e Initial load
duke
parents:
diff changeset
224 print("before:");
a61af66fc99e Initial load
duke
parents:
diff changeset
225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
226 assert(!is_empty(), "shouldn't dequeue from empty list");
a61af66fc99e Initial load
duke
parents:
diff changeset
227 GCTask* result = remove();
a61af66fc99e Initial load
duke
parents:
diff changeset
228 assert(result != NULL, "shouldn't have NULL task");
a61af66fc99e Initial load
duke
parents:
diff changeset
229 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
230 tty->print_cr(" return: " INTPTR_FORMAT, result);
a61af66fc99e Initial load
duke
parents:
diff changeset
231 print("after:");
a61af66fc99e Initial load
duke
parents:
diff changeset
232 }
a61af66fc99e Initial load
duke
parents:
diff changeset
233 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
235
a61af66fc99e Initial load
duke
parents:
diff changeset
236 // Dequeue one task, preferring one with affinity.
a61af66fc99e Initial load
duke
parents:
diff changeset
237 GCTask* GCTaskQueue::dequeue(uint affinity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
238 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
239 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
240 " GCTaskQueue::dequeue(%u)", this, affinity);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 print("before:");
a61af66fc99e Initial load
duke
parents:
diff changeset
242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
243 assert(!is_empty(), "shouldn't dequeue from empty list");
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // Look down to the next barrier for a task with this affinity.
a61af66fc99e Initial load
duke
parents:
diff changeset
245 GCTask* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
246 for (GCTask* element = remove_end();
a61af66fc99e Initial load
duke
parents:
diff changeset
247 element != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
248 element = element->newer()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
249 if (element->is_barrier_task()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // Don't consider barrier tasks, nor past them.
a61af66fc99e Initial load
duke
parents:
diff changeset
251 result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
252 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
254 if (element->affinity() == affinity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
255 result = remove(element);
a61af66fc99e Initial load
duke
parents:
diff changeset
256 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
259 // If we didn't find anything with affinity, just take the next task.
a61af66fc99e Initial load
duke
parents:
diff changeset
260 if (result == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
261 result = remove();
a61af66fc99e Initial load
duke
parents:
diff changeset
262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
263 if (TraceGCTaskQueue) {
a61af66fc99e Initial load
duke
parents:
diff changeset
264 tty->print_cr(" return: " INTPTR_FORMAT, result);
a61af66fc99e Initial load
duke
parents:
diff changeset
265 print("after:");
a61af66fc99e Initial load
duke
parents:
diff changeset
266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
267 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
269
a61af66fc99e Initial load
duke
parents:
diff changeset
270 GCTask* GCTaskQueue::remove() {
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // Dequeue from remove end.
a61af66fc99e Initial load
duke
parents:
diff changeset
272 GCTask* result = remove_end();
a61af66fc99e Initial load
duke
parents:
diff changeset
273 assert(result != NULL, "shouldn't have null task");
a61af66fc99e Initial load
duke
parents:
diff changeset
274 assert(result->older() == NULL, "not the remove_end");
a61af66fc99e Initial load
duke
parents:
diff changeset
275 set_remove_end(result->newer());
a61af66fc99e Initial load
duke
parents:
diff changeset
276 if (remove_end() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
277 assert(insert_end() == result, "not a singleton");
a61af66fc99e Initial load
duke
parents:
diff changeset
278 set_insert_end(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
279 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
280 remove_end()->set_older(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
282 result->set_newer(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
283 decrement_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
284 assert(result->newer() == NULL, "shouldn't be on queue");
a61af66fc99e Initial load
duke
parents:
diff changeset
285 assert(result->older() == NULL, "shouldn't be on queue");
a61af66fc99e Initial load
duke
parents:
diff changeset
286 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 GCTask* GCTaskQueue::remove(GCTask* task) {
a61af66fc99e Initial load
duke
parents:
diff changeset
290 // This is slightly more work, and has slightly fewer asserts
a61af66fc99e Initial load
duke
parents:
diff changeset
291 // than removing from the remove end.
a61af66fc99e Initial load
duke
parents:
diff changeset
292 assert(task != NULL, "shouldn't have null task");
a61af66fc99e Initial load
duke
parents:
diff changeset
293 GCTask* result = task;
a61af66fc99e Initial load
duke
parents:
diff changeset
294 if (result->newer() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
295 result->newer()->set_older(result->older());
a61af66fc99e Initial load
duke
parents:
diff changeset
296 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
297 assert(insert_end() == result, "not youngest");
a61af66fc99e Initial load
duke
parents:
diff changeset
298 set_insert_end(result->older());
a61af66fc99e Initial load
duke
parents:
diff changeset
299 }
a61af66fc99e Initial load
duke
parents:
diff changeset
300 if (result->older() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 result->older()->set_newer(result->newer());
a61af66fc99e Initial load
duke
parents:
diff changeset
302 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
303 assert(remove_end() == result, "not oldest");
a61af66fc99e Initial load
duke
parents:
diff changeset
304 set_remove_end(result->newer());
a61af66fc99e Initial load
duke
parents:
diff changeset
305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
306 result->set_newer(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
307 result->set_older(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
308 decrement_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
309 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
313 void GCTaskQueue::print(const char* message) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
314 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
a61af66fc99e Initial load
duke
parents:
diff changeset
315 " insert_end: " INTPTR_FORMAT
a61af66fc99e Initial load
duke
parents:
diff changeset
316 " remove_end: " INTPTR_FORMAT
a61af66fc99e Initial load
duke
parents:
diff changeset
317 " %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
318 this, insert_end(), remove_end(), message);
a61af66fc99e Initial load
duke
parents:
diff changeset
319 for (GCTask* element = insert_end();
a61af66fc99e Initial load
duke
parents:
diff changeset
320 element != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
321 element = element->older()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
322 element->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
323 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
324 }
a61af66fc99e Initial load
duke
parents:
diff changeset
325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
326 )
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328 //
a61af66fc99e Initial load
duke
parents:
diff changeset
329 // SynchronizedGCTaskQueue
a61af66fc99e Initial load
duke
parents:
diff changeset
330 //
a61af66fc99e Initial load
duke
parents:
diff changeset
331
a61af66fc99e Initial load
duke
parents:
diff changeset
332 SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
a61af66fc99e Initial load
duke
parents:
diff changeset
333 Monitor * lock_arg) :
a61af66fc99e Initial load
duke
parents:
diff changeset
334 _unsynchronized_queue(queue_arg),
a61af66fc99e Initial load
duke
parents:
diff changeset
335 _lock(lock_arg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
336 assert(unsynchronized_queue() != NULL, "null queue");
a61af66fc99e Initial load
duke
parents:
diff changeset
337 assert(lock() != NULL, "null lock");
a61af66fc99e Initial load
duke
parents:
diff changeset
338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
339
a61af66fc99e Initial load
duke
parents:
diff changeset
340 SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // Nothing to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
343
a61af66fc99e Initial load
duke
parents:
diff changeset
344 //
a61af66fc99e Initial load
duke
parents:
diff changeset
345 // GCTaskManager
a61af66fc99e Initial load
duke
parents:
diff changeset
346 //
a61af66fc99e Initial load
duke
parents:
diff changeset
347 GCTaskManager::GCTaskManager(uint workers) :
a61af66fc99e Initial load
duke
parents:
diff changeset
348 _workers(workers),
a61af66fc99e Initial load
duke
parents:
diff changeset
349 _ndc(NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
352
a61af66fc99e Initial load
duke
parents:
diff changeset
353 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
a61af66fc99e Initial load
duke
parents:
diff changeset
354 _workers(workers),
a61af66fc99e Initial load
duke
parents:
diff changeset
355 _ndc(ndc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
358
a61af66fc99e Initial load
duke
parents:
diff changeset
359 void GCTaskManager::initialize() {
a61af66fc99e Initial load
duke
parents:
diff changeset
360 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
361 tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
a61af66fc99e Initial load
duke
parents:
diff changeset
362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
363 assert(workers() != 0, "no workers");
a61af66fc99e Initial load
duke
parents:
diff changeset
364 _monitor = new Monitor(Mutex::barrier, // rank
a61af66fc99e Initial load
duke
parents:
diff changeset
365 "GCTaskManager monitor", // name
a61af66fc99e Initial load
duke
parents:
diff changeset
366 Mutex::_allow_vm_block_flag); // allow_vm_block
a61af66fc99e Initial load
duke
parents:
diff changeset
367 // The queue for the GCTaskManager must be a CHeapObj.
a61af66fc99e Initial load
duke
parents:
diff changeset
368 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
369 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
370 _noop_task = NoopGCTask::create_on_c_heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
371 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
a61af66fc99e Initial load
duke
parents:
diff changeset
372 {
a61af66fc99e Initial load
duke
parents:
diff changeset
373 // Set up worker threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
374 // Distribute the workers among the available processors,
a61af66fc99e Initial load
duke
parents:
diff changeset
375 // unless we were told not to, or if the os doesn't want to.
a61af66fc99e Initial load
duke
parents:
diff changeset
376 uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers());
a61af66fc99e Initial load
duke
parents:
diff changeset
377 if (!BindGCTaskThreadsToCPUs ||
a61af66fc99e Initial load
duke
parents:
diff changeset
378 !os::distribute_processes(workers(), processor_assignment)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
379 for (uint a = 0; a < workers(); a += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
380 processor_assignment[a] = sentinel_worker();
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
383 _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers());
a61af66fc99e Initial load
duke
parents:
diff changeset
384 for (uint t = 0; t < workers(); t += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
385 set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
a61af66fc99e Initial load
duke
parents:
diff changeset
386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
387 if (TraceGCTaskThread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
388 tty->print("GCTaskManager::initialize: distribution:");
a61af66fc99e Initial load
duke
parents:
diff changeset
389 for (uint t = 0; t < workers(); t += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 tty->print(" %u", processor_assignment[t]);
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
394 FREE_C_HEAP_ARRAY(uint, processor_assignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
395 }
a61af66fc99e Initial load
duke
parents:
diff changeset
396 reset_busy_workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
397 set_unblocked();
a61af66fc99e Initial load
duke
parents:
diff changeset
398 for (uint w = 0; w < workers(); w += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
399 set_resource_flag(w, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
401 reset_delivered_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
402 reset_completed_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
403 reset_noop_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
404 reset_barriers();
a61af66fc99e Initial load
duke
parents:
diff changeset
405 reset_emptied_queue();
a61af66fc99e Initial load
duke
parents:
diff changeset
406 for (uint s = 0; s < workers(); s += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
407 thread(s)->start();
a61af66fc99e Initial load
duke
parents:
diff changeset
408 }
a61af66fc99e Initial load
duke
parents:
diff changeset
409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
410
a61af66fc99e Initial load
duke
parents:
diff changeset
411 GCTaskManager::~GCTaskManager() {
a61af66fc99e Initial load
duke
parents:
diff changeset
412 assert(busy_workers() == 0, "still have busy workers");
a61af66fc99e Initial load
duke
parents:
diff changeset
413 assert(queue()->is_empty(), "still have queued work");
a61af66fc99e Initial load
duke
parents:
diff changeset
414 NoopGCTask::destroy(_noop_task);
a61af66fc99e Initial load
duke
parents:
diff changeset
415 _noop_task = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
416 if (_thread != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
417 for (uint i = 0; i < workers(); i += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
418 GCTaskThread::destroy(thread(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
419 set_thread(i, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
421 FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
422 _thread = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
424 if (_resource_flag != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
425 FREE_C_HEAP_ARRAY(bool, _resource_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
426 _resource_flag = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
428 if (queue() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
429 GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
a61af66fc99e Initial load
duke
parents:
diff changeset
430 GCTaskQueue::destroy(unsynchronized_queue);
a61af66fc99e Initial load
duke
parents:
diff changeset
431 SynchronizedGCTaskQueue::destroy(queue());
a61af66fc99e Initial load
duke
parents:
diff changeset
432 _queue = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
434 if (monitor() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
435 delete monitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
436 _monitor = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
439
a61af66fc99e Initial load
duke
parents:
diff changeset
440 void GCTaskManager::print_task_time_stamps() {
a61af66fc99e Initial load
duke
parents:
diff changeset
441 for(uint i=0; i<ParallelGCThreads; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
442 GCTaskThread* t = thread(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
443 t->print_task_time_stamps();
a61af66fc99e Initial load
duke
parents:
diff changeset
444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
446
a61af66fc99e Initial load
duke
parents:
diff changeset
447 void GCTaskManager::print_threads_on(outputStream* st) {
a61af66fc99e Initial load
duke
parents:
diff changeset
448 uint num_thr = workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
449 for (uint i = 0; i < num_thr; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
450 thread(i)->print_on(st);
a61af66fc99e Initial load
duke
parents:
diff changeset
451 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
454
a61af66fc99e Initial load
duke
parents:
diff changeset
455 void GCTaskManager::threads_do(ThreadClosure* tc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
456 assert(tc != NULL, "Null ThreadClosure");
a61af66fc99e Initial load
duke
parents:
diff changeset
457 uint num_thr = workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
458 for (uint i = 0; i < num_thr; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 tc->do_thread(thread(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
461 }
a61af66fc99e Initial load
duke
parents:
diff changeset
462
a61af66fc99e Initial load
duke
parents:
diff changeset
463 GCTaskThread* GCTaskManager::thread(uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
464 assert(which < workers(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
465 assert(_thread[which] != NULL, "shouldn't have null thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
466 return _thread[which];
a61af66fc99e Initial load
duke
parents:
diff changeset
467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
468
a61af66fc99e Initial load
duke
parents:
diff changeset
469 void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
470 assert(which < workers(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
471 assert(value != NULL, "shouldn't have null thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
472 _thread[which] = value;
a61af66fc99e Initial load
duke
parents:
diff changeset
473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
474
a61af66fc99e Initial load
duke
parents:
diff changeset
475 void GCTaskManager::add_task(GCTask* task) {
a61af66fc99e Initial load
duke
parents:
diff changeset
476 assert(task != NULL, "shouldn't have null task");
a61af66fc99e Initial load
duke
parents:
diff changeset
477 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
478 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
479 tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
a61af66fc99e Initial load
duke
parents:
diff changeset
480 task, GCTask::Kind::to_string(task->kind()));
a61af66fc99e Initial load
duke
parents:
diff changeset
481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 queue()->enqueue(task);
a61af66fc99e Initial load
duke
parents:
diff changeset
483 // Notify with the lock held to avoid missed notifies.
a61af66fc99e Initial load
duke
parents:
diff changeset
484 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 tty->print_cr(" GCTaskManager::add_task (%s)->notify_all",
a61af66fc99e Initial load
duke
parents:
diff changeset
486 monitor()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
488 (void) monitor()->notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // Release monitor().
a61af66fc99e Initial load
duke
parents:
diff changeset
490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
491
a61af66fc99e Initial load
duke
parents:
diff changeset
492 void GCTaskManager::add_list(GCTaskQueue* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
493 assert(list != NULL, "shouldn't have null task");
a61af66fc99e Initial load
duke
parents:
diff changeset
494 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
495 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
496 tty->print_cr("GCTaskManager::add_list(%u)", list->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
498 queue()->enqueue(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // Notify with the lock held to avoid missed notifies.
a61af66fc99e Initial load
duke
parents:
diff changeset
500 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
501 tty->print_cr(" GCTaskManager::add_list (%s)->notify_all",
a61af66fc99e Initial load
duke
parents:
diff changeset
502 monitor()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
504 (void) monitor()->notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
505 // Release monitor().
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 GCTask* GCTaskManager::get_task(uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
509 GCTask* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
510 // Grab the queue lock.
a61af66fc99e Initial load
duke
parents:
diff changeset
511 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // Wait while the queue is block or
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // there is nothing to do, except maybe release resources.
a61af66fc99e Initial load
duke
parents:
diff changeset
514 while (is_blocked() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
515 (queue()->is_empty() && !should_release_resources(which))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
516 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
517 tty->print_cr("GCTaskManager::get_task(%u)"
a61af66fc99e Initial load
duke
parents:
diff changeset
518 " blocked: %s"
a61af66fc99e Initial load
duke
parents:
diff changeset
519 " empty: %s"
a61af66fc99e Initial load
duke
parents:
diff changeset
520 " release: %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
521 which,
a61af66fc99e Initial load
duke
parents:
diff changeset
522 is_blocked() ? "true" : "false",
a61af66fc99e Initial load
duke
parents:
diff changeset
523 queue()->is_empty() ? "true" : "false",
a61af66fc99e Initial load
duke
parents:
diff changeset
524 should_release_resources(which) ? "true" : "false");
a61af66fc99e Initial load
duke
parents:
diff changeset
525 tty->print_cr(" => (%s)->wait()",
a61af66fc99e Initial load
duke
parents:
diff changeset
526 monitor()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
528 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
529 }
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // We've reacquired the queue lock here.
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // Figure out which condition caused us to exit the loop above.
a61af66fc99e Initial load
duke
parents:
diff changeset
532 if (!queue()->is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
533 if (UseGCTaskAffinity) {
a61af66fc99e Initial load
duke
parents:
diff changeset
534 result = queue()->dequeue(which);
a61af66fc99e Initial load
duke
parents:
diff changeset
535 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
536 result = queue()->dequeue();
a61af66fc99e Initial load
duke
parents:
diff changeset
537 }
a61af66fc99e Initial load
duke
parents:
diff changeset
538 if (result->is_barrier_task()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 assert(which != sentinel_worker(),
a61af66fc99e Initial load
duke
parents:
diff changeset
540 "blocker shouldn't be bogus");
a61af66fc99e Initial load
duke
parents:
diff changeset
541 set_blocking_worker(which);
a61af66fc99e Initial load
duke
parents:
diff changeset
542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
543 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
544 // The queue is empty, but we were woken up.
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // Just hand back a Noop task,
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // in case someone wanted us to release resources, or whatever.
a61af66fc99e Initial load
duke
parents:
diff changeset
547 result = noop_task();
a61af66fc99e Initial load
duke
parents:
diff changeset
548 increment_noop_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
549 }
a61af66fc99e Initial load
duke
parents:
diff changeset
550 assert(result != NULL, "shouldn't have null task");
a61af66fc99e Initial load
duke
parents:
diff changeset
551 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
552 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
a61af66fc99e Initial load
duke
parents:
diff changeset
553 which, result, GCTask::Kind::to_string(result->kind()));
a61af66fc99e Initial load
duke
parents:
diff changeset
554 tty->print_cr(" %s", result->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
556 increment_busy_workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
557 increment_delivered_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
558 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
559 // Release monitor().
a61af66fc99e Initial load
duke
parents:
diff changeset
560 }
a61af66fc99e Initial load
duke
parents:
diff changeset
561
a61af66fc99e Initial load
duke
parents:
diff changeset
562 void GCTaskManager::note_completion(uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
563 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
564 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
565 tty->print_cr("GCTaskManager::note_completion(%u)", which);
a61af66fc99e Initial load
duke
parents:
diff changeset
566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
567 // If we are blocked, check if the completing thread is the blocker.
a61af66fc99e Initial load
duke
parents:
diff changeset
568 if (blocking_worker() == which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
569 assert(blocking_worker() != sentinel_worker(),
a61af66fc99e Initial load
duke
parents:
diff changeset
570 "blocker shouldn't be bogus");
a61af66fc99e Initial load
duke
parents:
diff changeset
571 increment_barriers();
a61af66fc99e Initial load
duke
parents:
diff changeset
572 set_unblocked();
a61af66fc99e Initial load
duke
parents:
diff changeset
573 }
a61af66fc99e Initial load
duke
parents:
diff changeset
574 increment_completed_tasks();
a61af66fc99e Initial load
duke
parents:
diff changeset
575 uint active = decrement_busy_workers();
a61af66fc99e Initial load
duke
parents:
diff changeset
576 if ((active == 0) && (queue()->is_empty())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
577 increment_emptied_queue();
a61af66fc99e Initial load
duke
parents:
diff changeset
578 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
579 tty->print_cr(" GCTaskManager::note_completion(%u) done", which);
a61af66fc99e Initial load
duke
parents:
diff changeset
580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
581 // Notify client that we are done.
a61af66fc99e Initial load
duke
parents:
diff changeset
582 NotifyDoneClosure* ndc = notify_done_closure();
a61af66fc99e Initial load
duke
parents:
diff changeset
583 if (ndc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
584 ndc->notify(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
587 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
588 tty->print_cr(" GCTaskManager::note_completion(%u) (%s)->notify_all",
a61af66fc99e Initial load
duke
parents:
diff changeset
589 which, monitor()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
590 tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
591 " blocked: %s"
a61af66fc99e Initial load
duke
parents:
diff changeset
592 " empty: %s"
a61af66fc99e Initial load
duke
parents:
diff changeset
593 " release: %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
594 is_blocked() ? "true" : "false",
a61af66fc99e Initial load
duke
parents:
diff changeset
595 queue()->is_empty() ? "true" : "false",
a61af66fc99e Initial load
duke
parents:
diff changeset
596 should_release_resources(which) ? "true" : "false");
a61af66fc99e Initial load
duke
parents:
diff changeset
597 tty->print_cr(" "
a61af66fc99e Initial load
duke
parents:
diff changeset
598 " delivered: %u"
a61af66fc99e Initial load
duke
parents:
diff changeset
599 " completed: %u"
a61af66fc99e Initial load
duke
parents:
diff changeset
600 " barriers: %u"
a61af66fc99e Initial load
duke
parents:
diff changeset
601 " emptied: %u",
a61af66fc99e Initial load
duke
parents:
diff changeset
602 delivered_tasks(),
a61af66fc99e Initial load
duke
parents:
diff changeset
603 completed_tasks(),
a61af66fc99e Initial load
duke
parents:
diff changeset
604 barriers(),
a61af66fc99e Initial load
duke
parents:
diff changeset
605 emptied_queue());
a61af66fc99e Initial load
duke
parents:
diff changeset
606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
607 // Tell everyone that a task has completed.
a61af66fc99e Initial load
duke
parents:
diff changeset
608 (void) monitor()->notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
609 // Release monitor().
a61af66fc99e Initial load
duke
parents:
diff changeset
610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
611
a61af66fc99e Initial load
duke
parents:
diff changeset
612 uint GCTaskManager::increment_busy_workers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
613 assert(queue()->own_lock(), "don't own the lock");
a61af66fc99e Initial load
duke
parents:
diff changeset
614 _busy_workers += 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
615 return _busy_workers;
a61af66fc99e Initial load
duke
parents:
diff changeset
616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
617
a61af66fc99e Initial load
duke
parents:
diff changeset
618 uint GCTaskManager::decrement_busy_workers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
619 assert(queue()->own_lock(), "don't own the lock");
a61af66fc99e Initial load
duke
parents:
diff changeset
620 _busy_workers -= 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
621 return _busy_workers;
a61af66fc99e Initial load
duke
parents:
diff changeset
622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
623
a61af66fc99e Initial load
duke
parents:
diff changeset
624 void GCTaskManager::release_all_resources() {
a61af66fc99e Initial load
duke
parents:
diff changeset
625 // If you want this to be done atomically, do it in a BarrierGCTask.
a61af66fc99e Initial load
duke
parents:
diff changeset
626 for (uint i = 0; i < workers(); i += 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
627 set_resource_flag(i, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
629 }
a61af66fc99e Initial load
duke
parents:
diff changeset
630
a61af66fc99e Initial load
duke
parents:
diff changeset
631 bool GCTaskManager::should_release_resources(uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // This can be done without a lock because each thread reads one element.
a61af66fc99e Initial load
duke
parents:
diff changeset
633 return resource_flag(which);
a61af66fc99e Initial load
duke
parents:
diff changeset
634 }
a61af66fc99e Initial load
duke
parents:
diff changeset
635
a61af66fc99e Initial load
duke
parents:
diff changeset
636 void GCTaskManager::note_release(uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
637 // This can be done without a lock because each thread writes one element.
a61af66fc99e Initial load
duke
parents:
diff changeset
638 set_resource_flag(which, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
640
a61af66fc99e Initial load
duke
parents:
diff changeset
641 void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
642 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
a61af66fc99e Initial load
duke
parents:
diff changeset
643 list->enqueue(fin);
a61af66fc99e Initial load
duke
parents:
diff changeset
644 add_list(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
645 fin->wait_for();
a61af66fc99e Initial load
duke
parents:
diff changeset
646 // We have to release the barrier tasks!
a61af66fc99e Initial load
duke
parents:
diff changeset
647 WaitForBarrierGCTask::destroy(fin);
a61af66fc99e Initial load
duke
parents:
diff changeset
648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
649
a61af66fc99e Initial load
duke
parents:
diff changeset
650 bool GCTaskManager::resource_flag(uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
651 assert(which < workers(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
652 return _resource_flag[which];
a61af66fc99e Initial load
duke
parents:
diff changeset
653 }
a61af66fc99e Initial load
duke
parents:
diff changeset
654
a61af66fc99e Initial load
duke
parents:
diff changeset
655 void GCTaskManager::set_resource_flag(uint which, bool value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
656 assert(which < workers(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
657 _resource_flag[which] = value;
a61af66fc99e Initial load
duke
parents:
diff changeset
658 }
a61af66fc99e Initial load
duke
parents:
diff changeset
659
a61af66fc99e Initial load
duke
parents:
diff changeset
660 //
a61af66fc99e Initial load
duke
parents:
diff changeset
661 // NoopGCTask
a61af66fc99e Initial load
duke
parents:
diff changeset
662 //
a61af66fc99e Initial load
duke
parents:
diff changeset
663
a61af66fc99e Initial load
duke
parents:
diff changeset
664 NoopGCTask* NoopGCTask::create() {
a61af66fc99e Initial load
duke
parents:
diff changeset
665 NoopGCTask* result = new NoopGCTask(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
666 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
667 }
a61af66fc99e Initial load
duke
parents:
diff changeset
668
a61af66fc99e Initial load
duke
parents:
diff changeset
669 NoopGCTask* NoopGCTask::create_on_c_heap() {
a61af66fc99e Initial load
duke
parents:
diff changeset
670 NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
671 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
673
a61af66fc99e Initial load
duke
parents:
diff changeset
674 void NoopGCTask::destroy(NoopGCTask* that) {
a61af66fc99e Initial load
duke
parents:
diff changeset
675 if (that != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
676 that->destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
677 if (that->is_c_heap_obj()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
678 FreeHeap(that);
a61af66fc99e Initial load
duke
parents:
diff changeset
679 }
a61af66fc99e Initial load
duke
parents:
diff changeset
680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
681 }
a61af66fc99e Initial load
duke
parents:
diff changeset
682
a61af66fc99e Initial load
duke
parents:
diff changeset
683 void NoopGCTask::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
684 // This has to know it's superclass structure, just like the constructor.
a61af66fc99e Initial load
duke
parents:
diff changeset
685 this->GCTask::destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
686 // Nothing else to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
688
a61af66fc99e Initial load
duke
parents:
diff changeset
689 //
a61af66fc99e Initial load
duke
parents:
diff changeset
690 // BarrierGCTask
a61af66fc99e Initial load
duke
parents:
diff changeset
691 //
a61af66fc99e Initial load
duke
parents:
diff changeset
692
a61af66fc99e Initial load
duke
parents:
diff changeset
693 void BarrierGCTask::do_it(GCTaskManager* manager, uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // Wait for this to be the only busy worker.
a61af66fc99e Initial load
duke
parents:
diff changeset
695 // ??? I thought of having a StackObj class
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // whose constructor would grab the lock and come to the barrier,
a61af66fc99e Initial load
duke
parents:
diff changeset
697 // and whose destructor would release the lock,
a61af66fc99e Initial load
duke
parents:
diff changeset
698 // but that seems like too much mechanism for two lines of code.
a61af66fc99e Initial load
duke
parents:
diff changeset
699 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
700 do_it_internal(manager, which);
a61af66fc99e Initial load
duke
parents:
diff changeset
701 // Release manager->lock().
a61af66fc99e Initial load
duke
parents:
diff changeset
702 }
a61af66fc99e Initial load
duke
parents:
diff changeset
703
a61af66fc99e Initial load
duke
parents:
diff changeset
704 void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
705 // Wait for this to be the only busy worker.
a61af66fc99e Initial load
duke
parents:
diff changeset
706 assert(manager->monitor()->owned_by_self(), "don't own the lock");
a61af66fc99e Initial load
duke
parents:
diff changeset
707 assert(manager->is_blocked(), "manager isn't blocked");
a61af66fc99e Initial load
duke
parents:
diff changeset
708 while (manager->busy_workers() > 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
709 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
710 tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers",
a61af66fc99e Initial load
duke
parents:
diff changeset
711 which, manager->busy_workers());
a61af66fc99e Initial load
duke
parents:
diff changeset
712 }
a61af66fc99e Initial load
duke
parents:
diff changeset
713 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
714 }
a61af66fc99e Initial load
duke
parents:
diff changeset
715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
716
a61af66fc99e Initial load
duke
parents:
diff changeset
717 void BarrierGCTask::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
718 this->GCTask::destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
719 // Nothing else to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
721
a61af66fc99e Initial load
duke
parents:
diff changeset
722 //
a61af66fc99e Initial load
duke
parents:
diff changeset
723 // ReleasingBarrierGCTask
a61af66fc99e Initial load
duke
parents:
diff changeset
724 //
a61af66fc99e Initial load
duke
parents:
diff changeset
725
a61af66fc99e Initial load
duke
parents:
diff changeset
726 void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
727 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
728 do_it_internal(manager, which);
a61af66fc99e Initial load
duke
parents:
diff changeset
729 manager->release_all_resources();
a61af66fc99e Initial load
duke
parents:
diff changeset
730 // Release manager->lock().
a61af66fc99e Initial load
duke
parents:
diff changeset
731 }
a61af66fc99e Initial load
duke
parents:
diff changeset
732
a61af66fc99e Initial load
duke
parents:
diff changeset
733 void ReleasingBarrierGCTask::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
734 this->BarrierGCTask::destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
735 // Nothing else to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
736 }
a61af66fc99e Initial load
duke
parents:
diff changeset
737
a61af66fc99e Initial load
duke
parents:
diff changeset
738 //
a61af66fc99e Initial load
duke
parents:
diff changeset
739 // NotifyingBarrierGCTask
a61af66fc99e Initial load
duke
parents:
diff changeset
740 //
a61af66fc99e Initial load
duke
parents:
diff changeset
741
a61af66fc99e Initial load
duke
parents:
diff changeset
742 void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
743 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
744 do_it_internal(manager, which);
a61af66fc99e Initial load
duke
parents:
diff changeset
745 NotifyDoneClosure* ndc = notify_done_closure();
a61af66fc99e Initial load
duke
parents:
diff changeset
746 if (ndc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
747 ndc->notify(manager);
a61af66fc99e Initial load
duke
parents:
diff changeset
748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
749 // Release manager->lock().
a61af66fc99e Initial load
duke
parents:
diff changeset
750 }
a61af66fc99e Initial load
duke
parents:
diff changeset
751
a61af66fc99e Initial load
duke
parents:
diff changeset
752 void NotifyingBarrierGCTask::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
753 this->BarrierGCTask::destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
754 // Nothing else to do.
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 // WaitForBarrierGCTask
a61af66fc99e Initial load
duke
parents:
diff changeset
759 //
a61af66fc99e Initial load
duke
parents:
diff changeset
760 WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
a61af66fc99e Initial load
duke
parents:
diff changeset
761 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
762 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
763 }
a61af66fc99e Initial load
duke
parents:
diff changeset
764
a61af66fc99e Initial load
duke
parents:
diff changeset
765 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
a61af66fc99e Initial load
duke
parents:
diff changeset
766 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
767 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
768 }
a61af66fc99e Initial load
duke
parents:
diff changeset
769
a61af66fc99e Initial load
duke
parents:
diff changeset
770 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
a61af66fc99e Initial load
duke
parents:
diff changeset
771 _is_c_heap_obj(on_c_heap) {
a61af66fc99e Initial load
duke
parents:
diff changeset
772 _monitor = MonitorSupply::reserve();
a61af66fc99e Initial load
duke
parents:
diff changeset
773 set_should_wait(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
774 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
775 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
776 " WaitForBarrierGCTask::WaitForBarrierGCTask()"
a61af66fc99e Initial load
duke
parents:
diff changeset
777 " monitor: " INTPTR_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
778 this, monitor());
a61af66fc99e Initial load
duke
parents:
diff changeset
779 }
a61af66fc99e Initial load
duke
parents:
diff changeset
780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
781
a61af66fc99e Initial load
duke
parents:
diff changeset
782 void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
a61af66fc99e Initial load
duke
parents:
diff changeset
783 if (that != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
785 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
786 " WaitForBarrierGCTask::destroy()"
a61af66fc99e Initial load
duke
parents:
diff changeset
787 " is_c_heap_obj: %s"
a61af66fc99e Initial load
duke
parents:
diff changeset
788 " monitor: " INTPTR_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
789 that,
a61af66fc99e Initial load
duke
parents:
diff changeset
790 that->is_c_heap_obj() ? "true" : "false",
a61af66fc99e Initial load
duke
parents:
diff changeset
791 that->monitor());
a61af66fc99e Initial load
duke
parents:
diff changeset
792 }
a61af66fc99e Initial load
duke
parents:
diff changeset
793 that->destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
794 if (that->is_c_heap_obj()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
795 FreeHeap(that);
a61af66fc99e Initial load
duke
parents:
diff changeset
796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
797 }
a61af66fc99e Initial load
duke
parents:
diff changeset
798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
799
a61af66fc99e Initial load
duke
parents:
diff changeset
800 void WaitForBarrierGCTask::destruct() {
a61af66fc99e Initial load
duke
parents:
diff changeset
801 assert(monitor() != NULL, "monitor should not be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
802 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
803 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
804 " WaitForBarrierGCTask::destruct()"
a61af66fc99e Initial load
duke
parents:
diff changeset
805 " monitor: " INTPTR_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
806 this, monitor());
a61af66fc99e Initial load
duke
parents:
diff changeset
807 }
a61af66fc99e Initial load
duke
parents:
diff changeset
808 this->BarrierGCTask::destruct();
a61af66fc99e Initial load
duke
parents:
diff changeset
809 // Clean up that should be in the destructor,
a61af66fc99e Initial load
duke
parents:
diff changeset
810 // except that ResourceMarks don't call destructors.
a61af66fc99e Initial load
duke
parents:
diff changeset
811 if (monitor() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
812 MonitorSupply::release(monitor());
a61af66fc99e Initial load
duke
parents:
diff changeset
813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
814 _monitor = (Monitor*) 0xDEAD000F;
a61af66fc99e Initial load
duke
parents:
diff changeset
815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
816
a61af66fc99e Initial load
duke
parents:
diff changeset
817 void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
a61af66fc99e Initial load
duke
parents:
diff changeset
818 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
819 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
820 " WaitForBarrierGCTask::do_it() waiting for idle"
a61af66fc99e Initial load
duke
parents:
diff changeset
821 " monitor: " INTPTR_FORMAT,
a61af66fc99e Initial load
duke
parents:
diff changeset
822 this, monitor());
a61af66fc99e Initial load
duke
parents:
diff changeset
823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
824 {
a61af66fc99e Initial load
duke
parents:
diff changeset
825 // First, wait for the barrier to arrive.
a61af66fc99e Initial load
duke
parents:
diff changeset
826 MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
827 do_it_internal(manager, which);
a61af66fc99e Initial load
duke
parents:
diff changeset
828 // Release manager->lock().
a61af66fc99e Initial load
duke
parents:
diff changeset
829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
830 {
a61af66fc99e Initial load
duke
parents:
diff changeset
831 // Then notify the waiter.
a61af66fc99e Initial load
duke
parents:
diff changeset
832 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
833 set_should_wait(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
834 // Waiter doesn't miss the notify in the wait_for method
a61af66fc99e Initial load
duke
parents:
diff changeset
835 // since it checks the flag after grabbing the monitor.
a61af66fc99e Initial load
duke
parents:
diff changeset
836 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
837 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
838 " WaitForBarrierGCTask::do_it()"
a61af66fc99e Initial load
duke
parents:
diff changeset
839 " [" INTPTR_FORMAT "] (%s)->notify_all()",
a61af66fc99e Initial load
duke
parents:
diff changeset
840 this, monitor(), monitor()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
842 monitor()->notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
843 // Release monitor().
a61af66fc99e Initial load
duke
parents:
diff changeset
844 }
a61af66fc99e Initial load
duke
parents:
diff changeset
845 }
a61af66fc99e Initial load
duke
parents:
diff changeset
846
a61af66fc99e Initial load
duke
parents:
diff changeset
847 void WaitForBarrierGCTask::wait_for() {
a61af66fc99e Initial load
duke
parents:
diff changeset
848 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
849 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
850 " WaitForBarrierGCTask::wait_for()"
a61af66fc99e Initial load
duke
parents:
diff changeset
851 " should_wait: %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
852 this, should_wait() ? "true" : "false");
a61af66fc99e Initial load
duke
parents:
diff changeset
853 }
a61af66fc99e Initial load
duke
parents:
diff changeset
854 {
a61af66fc99e Initial load
duke
parents:
diff changeset
855 // Grab the lock and check again.
a61af66fc99e Initial load
duke
parents:
diff changeset
856 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
857 while (should_wait()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
858 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
859 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
860 " WaitForBarrierGCTask::wait_for()"
a61af66fc99e Initial load
duke
parents:
diff changeset
861 " [" INTPTR_FORMAT "] (%s)->wait()",
a61af66fc99e Initial load
duke
parents:
diff changeset
862 this, monitor(), monitor()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
864 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
866 // Reset the flag in case someone reuses this task.
a61af66fc99e Initial load
duke
parents:
diff changeset
867 set_should_wait(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
868 if (TraceGCTaskManager) {
a61af66fc99e Initial load
duke
parents:
diff changeset
869 tty->print_cr("[" INTPTR_FORMAT "]"
a61af66fc99e Initial load
duke
parents:
diff changeset
870 " WaitForBarrierGCTask::wait_for() returns"
a61af66fc99e Initial load
duke
parents:
diff changeset
871 " should_wait: %s",
a61af66fc99e Initial load
duke
parents:
diff changeset
872 this, should_wait() ? "true" : "false");
a61af66fc99e Initial load
duke
parents:
diff changeset
873 }
a61af66fc99e Initial load
duke
parents:
diff changeset
874 // Release monitor().
a61af66fc99e Initial load
duke
parents:
diff changeset
875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
876 }
a61af66fc99e Initial load
duke
parents:
diff changeset
877
a61af66fc99e Initial load
duke
parents:
diff changeset
878 Mutex* MonitorSupply::_lock = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
879 GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
880
a61af66fc99e Initial load
duke
parents:
diff changeset
881 Monitor* MonitorSupply::reserve() {
a61af66fc99e Initial load
duke
parents:
diff changeset
882 Monitor* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
883 // Lazy initialization: possible race.
a61af66fc99e Initial load
duke
parents:
diff changeset
884 if (lock() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
885 _lock = new Mutex(Mutex::barrier, // rank
a61af66fc99e Initial load
duke
parents:
diff changeset
886 "MonitorSupply mutex", // name
a61af66fc99e Initial load
duke
parents:
diff changeset
887 Mutex::_allow_vm_block_flag); // allow_vm_block
a61af66fc99e Initial load
duke
parents:
diff changeset
888 }
a61af66fc99e Initial load
duke
parents:
diff changeset
889 {
a61af66fc99e Initial load
duke
parents:
diff changeset
890 MutexLockerEx ml(lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
891 // Lazy initialization.
a61af66fc99e Initial load
duke
parents:
diff changeset
892 if (freelist() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
893 _freelist =
a61af66fc99e Initial load
duke
parents:
diff changeset
894 new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads,
a61af66fc99e Initial load
duke
parents:
diff changeset
895 true);
a61af66fc99e Initial load
duke
parents:
diff changeset
896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
897 if (! freelist()->is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
898 result = freelist()->pop();
a61af66fc99e Initial load
duke
parents:
diff changeset
899 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
900 result = new Monitor(Mutex::barrier, // rank
a61af66fc99e Initial load
duke
parents:
diff changeset
901 "MonitorSupply monitor", // name
a61af66fc99e Initial load
duke
parents:
diff changeset
902 Mutex::_allow_vm_block_flag); // allow_vm_block
a61af66fc99e Initial load
duke
parents:
diff changeset
903 }
a61af66fc99e Initial load
duke
parents:
diff changeset
904 guarantee(result != NULL, "shouldn't return NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
905 assert(!result->is_locked(), "shouldn't be locked");
a61af66fc99e Initial load
duke
parents:
diff changeset
906 // release lock().
a61af66fc99e Initial load
duke
parents:
diff changeset
907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
908 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
910
a61af66fc99e Initial load
duke
parents:
diff changeset
911 void MonitorSupply::release(Monitor* instance) {
a61af66fc99e Initial load
duke
parents:
diff changeset
912 assert(instance != NULL, "shouldn't release NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
913 assert(!instance->is_locked(), "shouldn't be locked");
a61af66fc99e Initial load
duke
parents:
diff changeset
914 {
a61af66fc99e Initial load
duke
parents:
diff changeset
915 MutexLockerEx ml(lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
916 freelist()->push(instance);
a61af66fc99e Initial load
duke
parents:
diff changeset
917 // release lock().
a61af66fc99e Initial load
duke
parents:
diff changeset
918 }
a61af66fc99e Initial load
duke
parents:
diff changeset
919 }