Mercurial > hg > truffle
annotate src/share/vm/utilities/workgroup.hpp @ 666:ebebd376f657
6805522: Server VM fails with assertion (block1->start() != block2->start(),"successors have unique bcis")
Reviewed-by: kvn
author | never |
---|---|
date | Mon, 23 Mar 2009 13:58:58 -0700 |
parents | 0fbdb4381b99 |
children | c18cbe5936b8 |
rev | line source |
---|---|
0 | 1 /* |
579 | 2 * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 // Forward declarations of classes defined here | |
26 | |
27 class WorkGang; | |
28 class GangWorker; | |
29 class YieldingFlexibleGangWorker; | |
30 class YieldingFlexibleGangTask; | |
31 class WorkData; | |
32 | |
33 // An abstract task to be worked on by a gang. | |
34 // You subclass this to supply your own work() method | |
549
fe3d7c11b4b7
6700941: G1: allocation spec missing for some G1 classes
apetrusenko
parents:
342
diff
changeset
|
35 class AbstractGangTask VALUE_OBJ_CLASS_SPEC { |
0 | 36 public: |
37 // The abstract work method. | |
38 // The argument tells you which member of the gang you are. | |
39 virtual void work(int i) = 0; | |
40 | |
41 // Debugging accessor for the name. | |
42 const char* name() const PRODUCT_RETURN_(return NULL;); | |
43 int counter() { return _counter; } | |
44 void set_counter(int value) { _counter = value; } | |
45 int *address_of_counter() { return &_counter; } | |
46 | |
47 // RTTI | |
48 NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const { | |
49 return false; | |
50 }) | |
51 | |
52 private: | |
53 NOT_PRODUCT(const char* _name;) | |
54 // ??? Should a task have a priority associated with it? | |
55 // ??? Or can the run method adjust priority as needed? | |
56 int _counter; | |
57 | |
58 protected: | |
59 // Constructor and desctructor: only construct subclasses. | |
60 AbstractGangTask(const char* name) { | |
61 NOT_PRODUCT(_name = name); | |
62 _counter = 0; | |
63 } | |
64 virtual ~AbstractGangTask() { } | |
65 }; | |
66 | |
67 | |
68 // Class AbstractWorkGang: | |
69 // An abstract class representing a gang of workers. | |
70 // You subclass this to supply an implementation of run_task(). | |
71 class AbstractWorkGang: public CHeapObj { | |
72 // Here's the public interface to this class. | |
73 public: | |
74 // Constructor and destructor. | |
342 | 75 AbstractWorkGang(const char* name, bool are_GC_task_threads, |
76 bool are_ConcurrentGC_threads); | |
0 | 77 ~AbstractWorkGang(); |
78 // Run a task, returns when the task is done (or terminated). | |
79 virtual void run_task(AbstractGangTask* task) = 0; | |
80 // Stop and terminate all workers. | |
81 virtual void stop(); | |
82 public: | |
83 // Debugging. | |
84 const char* name() const; | |
85 protected: | |
86 // Initialize only instance data. | |
342 | 87 const bool _are_GC_task_threads; |
88 const bool _are_ConcurrentGC_threads; | |
0 | 89 // Printing support. |
90 const char* _name; | |
91 // The monitor which protects these data, | |
92 // and notifies of changes in it. | |
93 Monitor* _monitor; | |
94 // The count of the number of workers in the gang. | |
95 int _total_workers; | |
96 // Whether the workers should terminate. | |
97 bool _terminate; | |
98 // The array of worker threads for this gang. | |
99 // This is only needed for cleaning up. | |
100 GangWorker** _gang_workers; | |
101 // The task for this gang. | |
102 AbstractGangTask* _task; | |
103 // A sequence number for the current task. | |
104 int _sequence_number; | |
105 // The number of started workers. | |
106 int _started_workers; | |
107 // The number of finished workers. | |
108 int _finished_workers; | |
109 public: | |
110 // Accessors for fields | |
111 Monitor* monitor() const { | |
112 return _monitor; | |
113 } | |
114 int total_workers() const { | |
115 return _total_workers; | |
116 } | |
117 bool terminate() const { | |
118 return _terminate; | |
119 } | |
120 GangWorker** gang_workers() const { | |
121 return _gang_workers; | |
122 } | |
123 AbstractGangTask* task() const { | |
124 return _task; | |
125 } | |
126 int sequence_number() const { | |
127 return _sequence_number; | |
128 } | |
129 int started_workers() const { | |
130 return _started_workers; | |
131 } | |
132 int finished_workers() const { | |
133 return _finished_workers; | |
134 } | |
342 | 135 bool are_GC_task_threads() const { |
136 return _are_GC_task_threads; | |
137 } | |
138 bool are_ConcurrentGC_threads() const { | |
139 return _are_ConcurrentGC_threads; | |
0 | 140 } |
141 // Predicates. | |
142 bool is_idle() const { | |
143 return (task() == NULL); | |
144 } | |
145 // Return the Ith gang worker. | |
146 GangWorker* gang_worker(int i) const; | |
147 | |
148 void threads_do(ThreadClosure* tc) const; | |
149 | |
150 // Printing | |
151 void print_worker_threads_on(outputStream *st) const; | |
152 void print_worker_threads() const { | |
153 print_worker_threads_on(tty); | |
154 } | |
155 | |
156 protected: | |
157 friend class GangWorker; | |
158 friend class YieldingFlexibleGangWorker; | |
159 // Note activation and deactivation of workers. | |
160 // These methods should only be called with the mutex held. | |
161 void internal_worker_poll(WorkData* data) const; | |
162 void internal_note_start(); | |
163 void internal_note_finish(); | |
164 }; | |
165 | |
166 class WorkData: public StackObj { | |
167 // This would be a struct, but I want accessor methods. | |
168 private: | |
169 bool _terminate; | |
170 AbstractGangTask* _task; | |
171 int _sequence_number; | |
172 public: | |
173 // Constructor and destructor | |
174 WorkData() { | |
175 _terminate = false; | |
176 _task = NULL; | |
177 _sequence_number = 0; | |
178 } | |
179 ~WorkData() { | |
180 } | |
181 // Accessors and modifiers | |
182 bool terminate() const { return _terminate; } | |
183 void set_terminate(bool value) { _terminate = value; } | |
184 AbstractGangTask* task() const { return _task; } | |
185 void set_task(AbstractGangTask* value) { _task = value; } | |
186 int sequence_number() const { return _sequence_number; } | |
187 void set_sequence_number(int value) { _sequence_number = value; } | |
188 | |
189 YieldingFlexibleGangTask* yf_task() const { | |
190 return (YieldingFlexibleGangTask*)_task; | |
191 } | |
192 }; | |
193 | |
194 // Class WorkGang: | |
195 class WorkGang: public AbstractWorkGang { | |
196 public: | |
197 // Constructor | |
342 | 198 WorkGang(const char* name, int workers, |
199 bool are_GC_task_threads, bool are_ConcurrentGC_threads); | |
0 | 200 // Run a task, returns when the task is done (or terminated). |
201 virtual void run_task(AbstractGangTask* task); | |
202 }; | |
203 | |
204 // Class GangWorker: | |
205 // Several instances of this class run in parallel as workers for a gang. | |
206 class GangWorker: public WorkerThread { | |
207 public: | |
208 // Constructors and destructor. | |
209 GangWorker(AbstractWorkGang* gang, uint id); | |
210 | |
211 // The only real method: run a task for the gang. | |
212 virtual void run(); | |
213 // Predicate for Thread | |
214 virtual bool is_GC_task_thread() const; | |
342 | 215 virtual bool is_ConcurrentGC_thread() const; |
0 | 216 // Printing |
217 void print_on(outputStream* st) const; | |
218 virtual void print() const { print_on(tty); } | |
219 protected: | |
220 AbstractWorkGang* _gang; | |
221 | |
222 virtual void initialize(); | |
223 virtual void loop(); | |
224 | |
225 public: | |
226 AbstractWorkGang* gang() const { return _gang; } | |
227 }; | |
228 | |
229 // A class that acts as a synchronisation barrier. Workers enter | |
230 // the barrier and must wait until all other workers have entered | |
231 // before any of them may leave. | |
232 | |
233 class WorkGangBarrierSync : public StackObj { | |
234 protected: | |
235 Monitor _monitor; | |
236 int _n_workers; | |
237 int _n_completed; | |
342 | 238 bool _should_reset; |
0 | 239 |
342 | 240 Monitor* monitor() { return &_monitor; } |
241 int n_workers() { return _n_workers; } | |
242 int n_completed() { return _n_completed; } | |
243 bool should_reset() { return _should_reset; } | |
0 | 244 |
342 | 245 void zero_completed() { _n_completed = 0; } |
246 void inc_completed() { _n_completed++; } | |
247 | |
248 void set_should_reset(bool v) { _should_reset = v; } | |
0 | 249 |
250 public: | |
251 WorkGangBarrierSync(); | |
252 WorkGangBarrierSync(int n_workers, const char* name); | |
253 | |
254 // Set the number of workers that will use the barrier. | |
255 // Must be called before any of the workers start running. | |
256 void set_n_workers(int n_workers); | |
257 | |
258 // Enter the barrier. A worker that enters the barrier will | |
259 // not be allowed to leave until all other threads have | |
260 // also entered the barrier. | |
261 void enter(); | |
262 }; | |
263 | |
264 // A class to manage claiming of subtasks within a group of tasks. The | |
265 // subtasks will be identified by integer indices, usually elements of an | |
266 // enumeration type. | |
267 | |
268 class SubTasksDone: public CHeapObj { | |
269 jint* _tasks; | |
270 int _n_tasks; | |
271 int _n_threads; | |
272 jint _threads_completed; | |
273 #ifdef ASSERT | |
274 jint _claimed; | |
275 #endif | |
276 | |
277 // Set all tasks to unclaimed. | |
278 void clear(); | |
279 | |
280 public: | |
281 // Initializes "this" to a state in which there are "n" tasks to be | |
282 // processed, none of the which are originally claimed. The number of | |
283 // threads doing the tasks is initialized 1. | |
284 SubTasksDone(int n); | |
285 | |
286 // True iff the object is in a valid state. | |
287 bool valid(); | |
288 | |
289 // Set the number of parallel threads doing the tasks to "t". Can only | |
290 // be called before tasks start or after they are complete. | |
291 void set_par_threads(int t); | |
292 | |
293 // Returns "false" if the task "t" is unclaimed, and ensures that task is | |
294 // claimed. The task "t" is required to be within the range of "this". | |
295 bool is_task_claimed(int t); | |
296 | |
297 // The calling thread asserts that it has attempted to claim all the | |
298 // tasks that it will try to claim. Every thread in the parallel task | |
299 // must execute this. (When the last thread does so, the task array is | |
300 // cleared.) | |
301 void all_tasks_completed(); | |
302 | |
303 // Destructor. | |
304 ~SubTasksDone(); | |
305 }; | |
306 | |
307 // As above, but for sequential tasks, i.e. instead of claiming | |
308 // sub-tasks from a set (possibly an enumeration), claim sub-tasks | |
309 // in sequential order. This is ideal for claiming dynamically | |
310 // partitioned tasks (like striding in the parallel remembered | |
311 // set scanning). Note that unlike the above class this is | |
312 // a stack object - is there any reason for it not to be? | |
313 | |
314 class SequentialSubTasksDone : public StackObj { | |
315 protected: | |
316 jint _n_tasks; // Total number of tasks available. | |
317 jint _n_claimed; // Number of tasks claimed. | |
318 jint _n_threads; // Total number of parallel threads. | |
319 jint _n_completed; // Number of completed threads. | |
320 | |
321 void clear(); | |
322 | |
323 public: | |
324 SequentialSubTasksDone() { clear(); } | |
325 ~SequentialSubTasksDone() {} | |
326 | |
327 // True iff the object is in a valid state. | |
328 bool valid(); | |
329 | |
330 // number of tasks | |
331 jint n_tasks() const { return _n_tasks; } | |
332 | |
333 // Set the number of parallel threads doing the tasks to t. | |
334 // Should be called before the task starts but it is safe | |
335 // to call this once a task is running provided that all | |
336 // threads agree on the number of threads. | |
337 void set_par_threads(int t) { _n_threads = t; } | |
338 | |
339 // Set the number of tasks to be claimed to t. As above, | |
340 // should be called before the tasks start but it is safe | |
341 // to call this once a task is running provided all threads | |
342 // agree on the number of tasks. | |
343 void set_n_tasks(int t) { _n_tasks = t; } | |
344 | |
345 // Returns false if the next task in the sequence is unclaimed, | |
346 // and ensures that it is claimed. Will set t to be the index | |
347 // of the claimed task in the sequence. Will return true if | |
348 // the task cannot be claimed and there are none left to claim. | |
349 bool is_task_claimed(int& t); | |
350 | |
351 // The calling thread asserts that it has attempted to claim | |
352 // all the tasks it possibly can in the sequence. Every thread | |
353 // claiming tasks must promise call this. Returns true if this | |
354 // is the last thread to complete so that the thread can perform | |
355 // cleanup if necessary. | |
356 bool all_tasks_completed(); | |
357 }; | |
342 | 358 |
359 // Represents a set of free small integer ids. | |
360 class FreeIdSet { | |
361 enum { | |
362 end_of_list = -1, | |
363 claimed = -2 | |
364 }; | |
365 | |
366 int _sz; | |
367 Monitor* _mon; | |
368 | |
369 int* _ids; | |
370 int _hd; | |
371 int _waiters; | |
372 int _claimed; | |
373 | |
374 static bool _safepoint; | |
375 typedef FreeIdSet* FreeIdSetPtr; | |
376 static const int NSets = 10; | |
377 static FreeIdSetPtr _sets[NSets]; | |
378 static bool _stat_init; | |
379 int _index; | |
380 | |
381 public: | |
382 FreeIdSet(int sz, Monitor* mon); | |
383 ~FreeIdSet(); | |
384 | |
385 static void set_safepoint(bool b); | |
386 | |
387 // Attempt to claim the given id permanently. Returns "true" iff | |
388 // successful. | |
389 bool claim_perm_id(int i); | |
390 | |
391 // Returns an unclaimed parallel id (waiting for one to be released if | |
392 // necessary). Returns "-1" if a GC wakes up a wait for an id. | |
393 int claim_par_id(); | |
394 | |
395 void release_par_id(int id); | |
396 }; |