annotate src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 1091:6aa7255741f3

6906727: UseCompressedOops: some card-marking fixes related to object arrays Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17). Reviewed-by: kvn, coleenp, jmasa
author ysr
date Thu, 03 Dec 2009 15:01:57 -0800
parents a61af66fc99e
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 }