src/share/vm/utilities/workgroup.hpp

Wed, 14 Dec 2011 13:34:57 -0800

author
jmasa
date
Wed, 14 Dec 2011 13:34:57 -0800
changeset 3357
441e946dc1af
parent 3294
bca17e38de00
child 3900
d2a62e0f25eb
permissions
-rw-r--r--

7121618: Change type of number of GC workers to unsigned int.
Summary: Change variables representing the number of GC workers to uint from int and size_t. Change the parameter in work(int i) to work(uint worker_id).
Reviewed-by: brutisso, tonyp

duke@435 1 /*
ysr@2651 2 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #ifndef SHARE_VM_UTILITIES_WORKGROUP_HPP
stefank@2314 26 #define SHARE_VM_UTILITIES_WORKGROUP_HPP
stefank@2314 27
stefank@2314 28 #include "utilities/taskqueue.hpp"
stefank@2314 29 #ifdef TARGET_OS_FAMILY_linux
stefank@2314 30 # include "thread_linux.inline.hpp"
stefank@2314 31 #endif
stefank@2314 32 #ifdef TARGET_OS_FAMILY_solaris
stefank@2314 33 # include "thread_solaris.inline.hpp"
stefank@2314 34 #endif
stefank@2314 35 #ifdef TARGET_OS_FAMILY_windows
stefank@2314 36 # include "thread_windows.inline.hpp"
stefank@2314 37 #endif
never@3156 38 #ifdef TARGET_OS_FAMILY_bsd
never@3156 39 # include "thread_bsd.inline.hpp"
never@3156 40 #endif
stefank@2314 41
ysr@2651 42 // Task class hierarchy:
ysr@2651 43 // AbstractGangTask
ysr@2651 44 // AbstractGangTaskWOopQueues
ysr@2651 45 //
ysr@2651 46 // Gang/Group class hierarchy:
ysr@2651 47 // AbstractWorkGang
ysr@2651 48 // WorkGang
ysr@2651 49 // FlexibleWorkGang
ysr@2651 50 // YieldingFlexibleWorkGang (defined in another file)
ysr@2651 51 //
ysr@2651 52 // Worker class hierarchy:
ysr@2651 53 // GangWorker (subclass of WorkerThread)
ysr@2651 54 // YieldingFlexibleGangWorker (defined in another file)
ysr@2651 55
duke@435 56 // Forward declarations of classes defined here
duke@435 57
duke@435 58 class WorkGang;
duke@435 59 class GangWorker;
duke@435 60 class YieldingFlexibleGangWorker;
duke@435 61 class YieldingFlexibleGangTask;
duke@435 62 class WorkData;
jmasa@2188 63 class AbstractWorkGang;
duke@435 64
duke@435 65 // An abstract task to be worked on by a gang.
duke@435 66 // You subclass this to supply your own work() method
apetrusenko@984 67 class AbstractGangTask VALUE_OBJ_CLASS_SPEC {
duke@435 68 public:
duke@435 69 // The abstract work method.
duke@435 70 // The argument tells you which member of the gang you are.
jmasa@3357 71 virtual void work(uint worker_id) = 0;
duke@435 72
jmasa@2188 73 // This method configures the task for proper termination.
jmasa@2188 74 // Some tasks do not have any requirements on termination
jmasa@2188 75 // and may inherit this method that does nothing. Some
jmasa@2188 76 // tasks do some coordination on termination and override
jmasa@2188 77 // this method to implement that coordination.
jmasa@2188 78 virtual void set_for_termination(int active_workers) {};
jmasa@2188 79
duke@435 80 // Debugging accessor for the name.
duke@435 81 const char* name() const PRODUCT_RETURN_(return NULL;);
duke@435 82 int counter() { return _counter; }
duke@435 83 void set_counter(int value) { _counter = value; }
duke@435 84 int *address_of_counter() { return &_counter; }
duke@435 85
duke@435 86 // RTTI
duke@435 87 NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const {
duke@435 88 return false;
duke@435 89 })
duke@435 90
duke@435 91 private:
duke@435 92 NOT_PRODUCT(const char* _name;)
duke@435 93 // ??? Should a task have a priority associated with it?
duke@435 94 // ??? Or can the run method adjust priority as needed?
duke@435 95 int _counter;
duke@435 96
duke@435 97 protected:
duke@435 98 // Constructor and desctructor: only construct subclasses.
jmasa@3294 99 AbstractGangTask(const char* name)
jmasa@3294 100 {
duke@435 101 NOT_PRODUCT(_name = name);
duke@435 102 _counter = 0;
duke@435 103 }
duke@435 104 virtual ~AbstractGangTask() { }
jmasa@3294 105
jmasa@3294 106 public:
duke@435 107 };
duke@435 108
jmasa@2188 109 class AbstractGangTaskWOopQueues : public AbstractGangTask {
jmasa@2188 110 OopTaskQueueSet* _queues;
jmasa@2188 111 ParallelTaskTerminator _terminator;
jmasa@2188 112 public:
jmasa@2188 113 AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) :
jmasa@2188 114 AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {}
jmasa@2188 115 ParallelTaskTerminator* terminator() { return &_terminator; }
jmasa@2188 116 virtual void set_for_termination(int active_workers) {
jmasa@2188 117 terminator()->reset_for_reuse(active_workers);
jmasa@2188 118 }
jmasa@2188 119 OopTaskQueueSet* queues() { return _queues; }
jmasa@2188 120 };
duke@435 121
jmasa@3294 122
duke@435 123 // Class AbstractWorkGang:
duke@435 124 // An abstract class representing a gang of workers.
duke@435 125 // You subclass this to supply an implementation of run_task().
duke@435 126 class AbstractWorkGang: public CHeapObj {
duke@435 127 // Here's the public interface to this class.
duke@435 128 public:
duke@435 129 // Constructor and destructor.
ysr@777 130 AbstractWorkGang(const char* name, bool are_GC_task_threads,
ysr@777 131 bool are_ConcurrentGC_threads);
duke@435 132 ~AbstractWorkGang();
duke@435 133 // Run a task, returns when the task is done (or terminated).
duke@435 134 virtual void run_task(AbstractGangTask* task) = 0;
duke@435 135 // Stop and terminate all workers.
duke@435 136 virtual void stop();
jmasa@3294 137 // Return true if more workers should be applied to the task.
jmasa@3294 138 virtual bool needs_more_workers() const { return true; }
duke@435 139 public:
duke@435 140 // Debugging.
duke@435 141 const char* name() const;
duke@435 142 protected:
duke@435 143 // Initialize only instance data.
ysr@777 144 const bool _are_GC_task_threads;
ysr@777 145 const bool _are_ConcurrentGC_threads;
duke@435 146 // Printing support.
duke@435 147 const char* _name;
duke@435 148 // The monitor which protects these data,
duke@435 149 // and notifies of changes in it.
duke@435 150 Monitor* _monitor;
duke@435 151 // The count of the number of workers in the gang.
jmasa@3357 152 uint _total_workers;
duke@435 153 // Whether the workers should terminate.
duke@435 154 bool _terminate;
duke@435 155 // The array of worker threads for this gang.
duke@435 156 // This is only needed for cleaning up.
duke@435 157 GangWorker** _gang_workers;
duke@435 158 // The task for this gang.
duke@435 159 AbstractGangTask* _task;
duke@435 160 // A sequence number for the current task.
duke@435 161 int _sequence_number;
duke@435 162 // The number of started workers.
jmasa@3357 163 uint _started_workers;
duke@435 164 // The number of finished workers.
jmasa@3357 165 uint _finished_workers;
duke@435 166 public:
duke@435 167 // Accessors for fields
duke@435 168 Monitor* monitor() const {
duke@435 169 return _monitor;
duke@435 170 }
jmasa@3357 171 uint total_workers() const {
duke@435 172 return _total_workers;
duke@435 173 }
jmasa@3357 174 virtual uint active_workers() const {
jmasa@2188 175 return _total_workers;
jmasa@2188 176 }
duke@435 177 bool terminate() const {
duke@435 178 return _terminate;
duke@435 179 }
duke@435 180 GangWorker** gang_workers() const {
duke@435 181 return _gang_workers;
duke@435 182 }
duke@435 183 AbstractGangTask* task() const {
duke@435 184 return _task;
duke@435 185 }
duke@435 186 int sequence_number() const {
duke@435 187 return _sequence_number;
duke@435 188 }
jmasa@3357 189 uint started_workers() const {
duke@435 190 return _started_workers;
duke@435 191 }
jmasa@3357 192 uint finished_workers() const {
duke@435 193 return _finished_workers;
duke@435 194 }
ysr@777 195 bool are_GC_task_threads() const {
ysr@777 196 return _are_GC_task_threads;
ysr@777 197 }
ysr@777 198 bool are_ConcurrentGC_threads() const {
ysr@777 199 return _are_ConcurrentGC_threads;
duke@435 200 }
duke@435 201 // Predicates.
duke@435 202 bool is_idle() const {
duke@435 203 return (task() == NULL);
duke@435 204 }
duke@435 205 // Return the Ith gang worker.
jmasa@3357 206 GangWorker* gang_worker(uint i) const;
duke@435 207
duke@435 208 void threads_do(ThreadClosure* tc) const;
duke@435 209
duke@435 210 // Printing
duke@435 211 void print_worker_threads_on(outputStream *st) const;
duke@435 212 void print_worker_threads() const {
duke@435 213 print_worker_threads_on(tty);
duke@435 214 }
duke@435 215
duke@435 216 protected:
duke@435 217 friend class GangWorker;
duke@435 218 friend class YieldingFlexibleGangWorker;
duke@435 219 // Note activation and deactivation of workers.
duke@435 220 // These methods should only be called with the mutex held.
duke@435 221 void internal_worker_poll(WorkData* data) const;
duke@435 222 void internal_note_start();
duke@435 223 void internal_note_finish();
duke@435 224 };
duke@435 225
duke@435 226 class WorkData: public StackObj {
duke@435 227 // This would be a struct, but I want accessor methods.
duke@435 228 private:
duke@435 229 bool _terminate;
duke@435 230 AbstractGangTask* _task;
duke@435 231 int _sequence_number;
duke@435 232 public:
duke@435 233 // Constructor and destructor
duke@435 234 WorkData() {
duke@435 235 _terminate = false;
duke@435 236 _task = NULL;
duke@435 237 _sequence_number = 0;
duke@435 238 }
duke@435 239 ~WorkData() {
duke@435 240 }
duke@435 241 // Accessors and modifiers
duke@435 242 bool terminate() const { return _terminate; }
duke@435 243 void set_terminate(bool value) { _terminate = value; }
duke@435 244 AbstractGangTask* task() const { return _task; }
duke@435 245 void set_task(AbstractGangTask* value) { _task = value; }
duke@435 246 int sequence_number() const { return _sequence_number; }
duke@435 247 void set_sequence_number(int value) { _sequence_number = value; }
duke@435 248
duke@435 249 YieldingFlexibleGangTask* yf_task() const {
duke@435 250 return (YieldingFlexibleGangTask*)_task;
duke@435 251 }
duke@435 252 };
duke@435 253
duke@435 254 // Class WorkGang:
duke@435 255 class WorkGang: public AbstractWorkGang {
duke@435 256 public:
duke@435 257 // Constructor
jmasa@3357 258 WorkGang(const char* name, uint workers,
ysr@777 259 bool are_GC_task_threads, bool are_ConcurrentGC_threads);
duke@435 260 // Run a task, returns when the task is done (or terminated).
duke@435 261 virtual void run_task(AbstractGangTask* task);
jmasa@2188 262 void run_task(AbstractGangTask* task, uint no_of_parallel_workers);
jmasa@2188 263 // Allocate a worker and return a pointer to it.
jmasa@3357 264 virtual GangWorker* allocate_worker(uint which);
jmasa@2188 265 // Initialize workers in the gang. Return true if initialization
jmasa@2188 266 // succeeded. The type of the worker can be overridden in a derived
jmasa@2188 267 // class with the appropriate implementation of allocate_worker().
jmasa@2188 268 bool initialize_workers();
duke@435 269 };
duke@435 270
duke@435 271 // Class GangWorker:
duke@435 272 // Several instances of this class run in parallel as workers for a gang.
duke@435 273 class GangWorker: public WorkerThread {
duke@435 274 public:
duke@435 275 // Constructors and destructor.
duke@435 276 GangWorker(AbstractWorkGang* gang, uint id);
duke@435 277
duke@435 278 // The only real method: run a task for the gang.
duke@435 279 virtual void run();
duke@435 280 // Predicate for Thread
duke@435 281 virtual bool is_GC_task_thread() const;
ysr@777 282 virtual bool is_ConcurrentGC_thread() const;
duke@435 283 // Printing
duke@435 284 void print_on(outputStream* st) const;
duke@435 285 virtual void print() const { print_on(tty); }
duke@435 286 protected:
duke@435 287 AbstractWorkGang* _gang;
duke@435 288
duke@435 289 virtual void initialize();
duke@435 290 virtual void loop();
duke@435 291
duke@435 292 public:
duke@435 293 AbstractWorkGang* gang() const { return _gang; }
duke@435 294 };
duke@435 295
jmasa@3294 296 // Dynamic number of worker threads
jmasa@3294 297 //
jmasa@3294 298 // This type of work gang is used to run different numbers of
jmasa@3294 299 // worker threads at different times. The
jmasa@3294 300 // number of workers run for a task is "_active_workers"
jmasa@3294 301 // instead of "_total_workers" in a WorkGang. The method
jmasa@3294 302 // "needs_more_workers()" returns true until "_active_workers"
jmasa@3294 303 // have been started and returns false afterwards. The
jmasa@3294 304 // implementation of "needs_more_workers()" in WorkGang always
jmasa@3294 305 // returns true so that all workers are started. The method
jmasa@3294 306 // "loop()" in GangWorker was modified to ask "needs_more_workers()"
jmasa@3294 307 // in its loop to decide if it should start working on a task.
jmasa@3294 308 // A worker in "loop()" waits for notification on the WorkGang
jmasa@3294 309 // monitor and execution of each worker as it checks for work
jmasa@3294 310 // is serialized via the same monitor. The "needs_more_workers()"
jmasa@3294 311 // call is serialized and additionally the calculation for the
jmasa@3294 312 // "part" (effectively the worker id for executing the task) is
jmasa@3294 313 // serialized to give each worker a unique "part". Workers that
jmasa@3294 314 // are not needed for this tasks (i.e., "_active_workers" have
jmasa@3294 315 // been started before it, continue to wait for work.
jmasa@3294 316
jmasa@2188 317 class FlexibleWorkGang: public WorkGang {
jmasa@3294 318 // The currently active workers in this gang.
jmasa@3294 319 // This is a number that is dynamically adjusted
jmasa@3294 320 // and checked in the run_task() method at each invocation.
jmasa@3294 321 // As described above _active_workers determines the number
jmasa@3294 322 // of threads started on a task. It must also be used to
jmasa@3294 323 // determine completion.
jmasa@3294 324
jmasa@2188 325 protected:
jmasa@3357 326 uint _active_workers;
jmasa@2188 327 public:
jmasa@2188 328 // Constructor and destructor.
jmasa@3294 329 // Initialize active_workers to a minimum value. Setting it to
jmasa@3294 330 // the parameter "workers" will initialize it to a maximum
jmasa@3294 331 // value which is not desirable.
jmasa@3357 332 FlexibleWorkGang(const char* name, uint workers,
jmasa@2188 333 bool are_GC_task_threads,
jmasa@2188 334 bool are_ConcurrentGC_threads) :
jmasa@3294 335 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
jmasa@3357 336 _active_workers(UseDynamicNumberOfGCThreads ? 1U : ParallelGCThreads) {}
jmasa@2188 337 // Accessors for fields
jmasa@3357 338 virtual uint active_workers() const { return _active_workers; }
jmasa@3357 339 void set_active_workers(uint v) {
jmasa@3294 340 assert(v <= _total_workers,
jmasa@3294 341 "Trying to set more workers active than there are");
jmasa@3294 342 _active_workers = MIN2(v, _total_workers);
jmasa@3294 343 assert(v != 0, "Trying to set active workers to 0");
jmasa@3357 344 _active_workers = MAX2(1U, _active_workers);
jmasa@3294 345 assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
jmasa@3294 346 "Unless dynamic should use total workers");
jmasa@3294 347 }
jmasa@3294 348 virtual void run_task(AbstractGangTask* task);
jmasa@3294 349 virtual bool needs_more_workers() const {
jmasa@3294 350 return _started_workers < _active_workers;
jmasa@3294 351 }
jmasa@2188 352 };
jmasa@2188 353
jmasa@2188 354 // Work gangs in garbage collectors: 2009-06-10
jmasa@2188 355 //
jmasa@2188 356 // SharedHeap - work gang for stop-the-world parallel collection.
jmasa@2188 357 // Used by
jmasa@2188 358 // ParNewGeneration
jmasa@2188 359 // CMSParRemarkTask
jmasa@2188 360 // CMSRefProcTaskExecutor
jmasa@2188 361 // G1CollectedHeap
jmasa@2188 362 // G1ParFinalCountTask
jmasa@2188 363 // ConcurrentMark
jmasa@2188 364 // CMSCollector
jmasa@2188 365
duke@435 366 // A class that acts as a synchronisation barrier. Workers enter
duke@435 367 // the barrier and must wait until all other workers have entered
duke@435 368 // before any of them may leave.
duke@435 369
duke@435 370 class WorkGangBarrierSync : public StackObj {
duke@435 371 protected:
duke@435 372 Monitor _monitor;
jmasa@3357 373 uint _n_workers;
jmasa@3357 374 uint _n_completed;
ysr@777 375 bool _should_reset;
duke@435 376
ysr@777 377 Monitor* monitor() { return &_monitor; }
jmasa@3357 378 uint n_workers() { return _n_workers; }
jmasa@3357 379 uint n_completed() { return _n_completed; }
ysr@777 380 bool should_reset() { return _should_reset; }
duke@435 381
ysr@777 382 void zero_completed() { _n_completed = 0; }
ysr@777 383 void inc_completed() { _n_completed++; }
ysr@777 384
ysr@777 385 void set_should_reset(bool v) { _should_reset = v; }
duke@435 386
duke@435 387 public:
duke@435 388 WorkGangBarrierSync();
jmasa@3357 389 WorkGangBarrierSync(uint n_workers, const char* name);
duke@435 390
duke@435 391 // Set the number of workers that will use the barrier.
duke@435 392 // Must be called before any of the workers start running.
jmasa@3357 393 void set_n_workers(uint n_workers);
duke@435 394
duke@435 395 // Enter the barrier. A worker that enters the barrier will
duke@435 396 // not be allowed to leave until all other threads have
duke@435 397 // also entered the barrier.
duke@435 398 void enter();
duke@435 399 };
duke@435 400
duke@435 401 // A class to manage claiming of subtasks within a group of tasks. The
duke@435 402 // subtasks will be identified by integer indices, usually elements of an
duke@435 403 // enumeration type.
duke@435 404
jmasa@3357 405 class SubTasksDone : public CHeapObj {
jmasa@3357 406 uint* _tasks;
jmasa@3357 407 uint _n_tasks;
jmasa@3294 408 // _n_threads is used to determine when a sub task is done.
jmasa@3294 409 // It does not control how many threads will execute the subtask
jmasa@3294 410 // but must be initialized to the number that do execute the task
jmasa@3294 411 // in order to correctly decide when the subtask is done (all the
jmasa@3294 412 // threads working on the task have finished).
jmasa@3357 413 uint _n_threads;
jmasa@3357 414 uint _threads_completed;
duke@435 415 #ifdef ASSERT
jmasa@3357 416 volatile uint _claimed;
duke@435 417 #endif
duke@435 418
duke@435 419 // Set all tasks to unclaimed.
duke@435 420 void clear();
duke@435 421
duke@435 422 public:
duke@435 423 // Initializes "this" to a state in which there are "n" tasks to be
duke@435 424 // processed, none of the which are originally claimed. The number of
duke@435 425 // threads doing the tasks is initialized 1.
jmasa@3357 426 SubTasksDone(uint n);
duke@435 427
duke@435 428 // True iff the object is in a valid state.
duke@435 429 bool valid();
duke@435 430
jmasa@2188 431 // Get/set the number of parallel threads doing the tasks to "t". Can only
duke@435 432 // be called before tasks start or after they are complete.
jmasa@3357 433 uint n_threads() { return _n_threads; }
jmasa@3357 434 void set_n_threads(uint t);
duke@435 435
duke@435 436 // Returns "false" if the task "t" is unclaimed, and ensures that task is
duke@435 437 // claimed. The task "t" is required to be within the range of "this".
jmasa@3357 438 bool is_task_claimed(uint t);
duke@435 439
duke@435 440 // The calling thread asserts that it has attempted to claim all the
duke@435 441 // tasks that it will try to claim. Every thread in the parallel task
duke@435 442 // must execute this. (When the last thread does so, the task array is
duke@435 443 // cleared.)
duke@435 444 void all_tasks_completed();
duke@435 445
duke@435 446 // Destructor.
duke@435 447 ~SubTasksDone();
duke@435 448 };
duke@435 449
duke@435 450 // As above, but for sequential tasks, i.e. instead of claiming
duke@435 451 // sub-tasks from a set (possibly an enumeration), claim sub-tasks
duke@435 452 // in sequential order. This is ideal for claiming dynamically
duke@435 453 // partitioned tasks (like striding in the parallel remembered
duke@435 454 // set scanning). Note that unlike the above class this is
duke@435 455 // a stack object - is there any reason for it not to be?
duke@435 456
duke@435 457 class SequentialSubTasksDone : public StackObj {
duke@435 458 protected:
jmasa@3357 459 uint _n_tasks; // Total number of tasks available.
jmasa@3357 460 uint _n_claimed; // Number of tasks claimed.
jmasa@2188 461 // _n_threads is used to determine when a sub task is done.
jmasa@2188 462 // See comments on SubTasksDone::_n_threads
jmasa@3357 463 uint _n_threads; // Total number of parallel threads.
jmasa@3357 464 uint _n_completed; // Number of completed threads.
duke@435 465
duke@435 466 void clear();
duke@435 467
duke@435 468 public:
jmasa@2188 469 SequentialSubTasksDone() {
jmasa@2188 470 clear();
jmasa@2188 471 }
duke@435 472 ~SequentialSubTasksDone() {}
duke@435 473
duke@435 474 // True iff the object is in a valid state.
duke@435 475 bool valid();
duke@435 476
duke@435 477 // number of tasks
jmasa@3357 478 uint n_tasks() const { return _n_tasks; }
duke@435 479
jmasa@2188 480 // Get/set the number of parallel threads doing the tasks to t.
duke@435 481 // Should be called before the task starts but it is safe
duke@435 482 // to call this once a task is running provided that all
duke@435 483 // threads agree on the number of threads.
jmasa@3357 484 uint n_threads() { return _n_threads; }
jmasa@3357 485 void set_n_threads(uint t) { _n_threads = t; }
duke@435 486
duke@435 487 // Set the number of tasks to be claimed to t. As above,
duke@435 488 // should be called before the tasks start but it is safe
duke@435 489 // to call this once a task is running provided all threads
duke@435 490 // agree on the number of tasks.
jmasa@3357 491 void set_n_tasks(uint t) { _n_tasks = t; }
duke@435 492
duke@435 493 // Returns false if the next task in the sequence is unclaimed,
duke@435 494 // and ensures that it is claimed. Will set t to be the index
duke@435 495 // of the claimed task in the sequence. Will return true if
duke@435 496 // the task cannot be claimed and there are none left to claim.
jmasa@3357 497 bool is_task_claimed(uint& t);
duke@435 498
duke@435 499 // The calling thread asserts that it has attempted to claim
duke@435 500 // all the tasks it possibly can in the sequence. Every thread
duke@435 501 // claiming tasks must promise call this. Returns true if this
duke@435 502 // is the last thread to complete so that the thread can perform
duke@435 503 // cleanup if necessary.
duke@435 504 bool all_tasks_completed();
duke@435 505 };
ysr@777 506
ysr@777 507 // Represents a set of free small integer ids.
ysr@777 508 class FreeIdSet {
ysr@777 509 enum {
ysr@777 510 end_of_list = -1,
ysr@777 511 claimed = -2
ysr@777 512 };
ysr@777 513
ysr@777 514 int _sz;
ysr@777 515 Monitor* _mon;
ysr@777 516
ysr@777 517 int* _ids;
ysr@777 518 int _hd;
ysr@777 519 int _waiters;
ysr@777 520 int _claimed;
ysr@777 521
ysr@777 522 static bool _safepoint;
ysr@777 523 typedef FreeIdSet* FreeIdSetPtr;
ysr@777 524 static const int NSets = 10;
ysr@777 525 static FreeIdSetPtr _sets[NSets];
ysr@777 526 static bool _stat_init;
ysr@777 527 int _index;
ysr@777 528
ysr@777 529 public:
ysr@777 530 FreeIdSet(int sz, Monitor* mon);
ysr@777 531 ~FreeIdSet();
ysr@777 532
ysr@777 533 static void set_safepoint(bool b);
ysr@777 534
ysr@777 535 // Attempt to claim the given id permanently. Returns "true" iff
ysr@777 536 // successful.
ysr@777 537 bool claim_perm_id(int i);
ysr@777 538
ysr@777 539 // Returns an unclaimed parallel id (waiting for one to be released if
ysr@777 540 // necessary). Returns "-1" if a GC wakes up a wait for an id.
ysr@777 541 int claim_par_id();
ysr@777 542
ysr@777 543 void release_par_id(int id);
ysr@777 544 };
stefank@2314 545
stefank@2314 546 #endif // SHARE_VM_UTILITIES_WORKGROUP_HPP

mercurial