426 return true;
427 }
428 return false;
429 }
430
431 template<class T, MEMFLAGS F>
432 uint GenericTaskQueueSet<T, F>::tasks() const {
433 uint n = 0;
434 for (uint j = 0; j < _n; j++) {
435 n += _queues[j]->size();
436 }
437 return n;
438 }
439
440 // When to terminate from the termination protocol.
441 class TerminatorTerminator: public CHeapObj<mtInternal> {
442 public:
443 virtual bool should_exit_termination() = 0;
444 };
445
446 // A class to aid in the termination of a set of parallel tasks using
447 // TaskQueueSet's for work stealing.
448
449 #undef TRACESPINNING
450
451 class ParallelTaskTerminator: public CHeapObj<mtGC> {
452 protected:
453 uint _n_threads;
454 TaskQueueSetSuper* _queue_set;
455
456 DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);
457 volatile uint _offered_termination;
458 DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile uint));
459
460 #ifdef TRACESPINNING
461 static uint _total_yields;
462 static uint _total_spins;
463 static uint _total_peeks;
464 #endif
465
466 bool peek_in_queue_set();
467 protected:
468 virtual void yield();
469 void sleep(uint millis);
470
471 // Called when exiting termination is requested.
472 // When the request is made, terminator may have already terminated
473 // (e.g. all threads are arrived and offered termination). In this case,
474 // it should ignore the request and complete the termination.
475 // Return true if termination is completed. Otherwise, return false.
476 bool complete_or_exit_termination();
477 public:
478
479 // "n_threads" is the number of threads to be terminated. "queue_set" is a
480 // queue sets of work queues of other threads.
481 ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
482 virtual ~ParallelTaskTerminator();
483
484 // The current thread has no work, and is ready to terminate if everyone
485 // else is. If returns "true", all threads are terminated. If returns
486 // "false", available work has been observed in one of the task queues,
487 // so the global task is not complete.
488 bool offer_termination() {
489 return offer_termination(NULL);
490 }
491
492 // As above, but it also terminates if the should_exit_termination()
493 // method of the terminator parameter returns true. If terminator is
494 // NULL, then it is ignored.
495 virtual bool offer_termination(TerminatorTerminator* terminator);
496
497 // Reset the terminator, so that it may be reused again.
498 // The caller is responsible for ensuring that this is done
499 // in an MT-safe manner, once the previous round of use of
500 // the terminator is finished.
501 void reset_for_reuse();
502 // Same as above but the number of parallel threads is set to the
503 // given number.
504 void reset_for_reuse(uint n_threads);
505
506 #ifdef TRACESPINNING
507 static uint total_yields() { return _total_yields; }
508 static uint total_spins() { return _total_spins; }
509 static uint total_peeks() { return _total_peeks; }
510 static void print_termination_counts();
511 #endif
512 };
513
514 class TaskTerminator : public StackObj {
515 private:
516 ParallelTaskTerminator* _terminator;
517
518 NONCOPYABLE(TaskTerminator);
519
520 public:
521 TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
522 ~TaskTerminator();
523
524 ParallelTaskTerminator* terminator() const {
525 return _terminator;
526 }
527 };
528
529 typedef GenericTaskQueue<oop, mtGC> OopTaskQueue;
530 typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
531
532 #ifdef _MSC_VER
533 #pragma warning(push)
534 // warning C4522: multiple assignment operators specified
535 #pragma warning(disable:4522)
536 #endif
537
538 // This is a container class for either an oop* or a narrowOop*.
539 // Both are pushed onto a task queue and the consumer will test is_narrow()
540 // to determine which should be processed.
541 class StarTask {
542 void* _holder; // either union oop* or narrowOop*
543
544 enum { COMPRESSED_OOP_MASK = 1 };
545
546 public:
547 StarTask(narrowOop* p) {
548 assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!");
|
426 return true;
427 }
428 return false;
429 }
430
431 template<class T, MEMFLAGS F>
432 uint GenericTaskQueueSet<T, F>::tasks() const {
433 uint n = 0;
434 for (uint j = 0; j < _n; j++) {
435 n += _queues[j]->size();
436 }
437 return n;
438 }
439
440 // When to terminate from the termination protocol.
441 class TerminatorTerminator: public CHeapObj<mtInternal> {
442 public:
443 virtual bool should_exit_termination() = 0;
444 };
445
446 typedef GenericTaskQueue<oop, mtGC> OopTaskQueue;
447 typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
448
449 #ifdef _MSC_VER
450 #pragma warning(push)
451 // warning C4522: multiple assignment operators specified
452 #pragma warning(disable:4522)
453 #endif
454
455 // This is a container class for either an oop* or a narrowOop*.
456 // Both are pushed onto a task queue and the consumer will test is_narrow()
457 // to determine which should be processed.
458 class StarTask {
459 void* _holder; // either union oop* or narrowOop*
460
461 enum { COMPRESSED_OOP_MASK = 1 };
462
463 public:
464 StarTask(narrowOop* p) {
465 assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!");
|