< prev index next >

src/hotspot/share/gc/shared/taskqueue.hpp

Print this page




 339   // Attempt to pop from the overflow stack; return true if anything was popped.
 340   inline bool pop_overflow(E& t);
 341 
 342   inline overflow_t* overflow_stack() { return &_overflow_stack; }
 343 
 344   inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
 345   inline bool overflow_empty()  const { return _overflow_stack.is_empty(); }
 346   inline bool is_empty()        const {
 347     return taskqueue_empty() && overflow_empty();
 348   }
 349 
 350 private:
 351   overflow_t _overflow_stack;
 352 };
 353 
 354 class TaskQueueSetSuper {
 355 protected:
 356   static int randomParkAndMiller(int* seed0);
 357 public:
 358   // Returns "true" if some TaskQueue in the set contains a task.
 359   virtual bool peek() = 0;

 360 };
 361 
 362 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
 363 };
 364 
 365 template<class T, MEMFLAGS F>
 366 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
 367 private:
 368   uint _n;
 369   T** _queues;
 370 
 371 public:
 372   typedef typename T::element_type E;
 373 
 374   GenericTaskQueueSet(int n);
 375   ~GenericTaskQueueSet();
 376 
 377   bool steal_best_of_2(uint queue_num, int* seed, E& t);
 378 
 379   void register_queue(uint i, T* q);
 380 
 381   T* queue(uint n);
 382 
 383   // The thread with queue number "queue_num" (and whose random number seed is
 384   // at "seed") is trying to steal a task from some other queue.  (It may try
 385   // several queues, according to some configuration parameter.)  If some steal
 386   // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
 387   // false.
 388   bool steal(uint queue_num, int* seed, E& t);
 389 
 390   bool peek();

 391 
 392   uint size() const { return _n; }
 393 };
 394 
 395 template<class T, MEMFLAGS F> void
 396 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
 397   assert(i < _n, "index out of range.");
 398   _queues[i] = q;
 399 }
 400 
 401 template<class T, MEMFLAGS F> T*
 402 GenericTaskQueueSet<T, F>::queue(uint i) {
 403   return _queues[i];
 404 }
 405 
 406 template<class T, MEMFLAGS F>
 407 bool GenericTaskQueueSet<T, F>::peek() {
 408   // Try all the queues.
 409   for (uint j = 0; j < _n; j++) {
 410     if (_queues[j]->peek())
 411       return true;
 412   }
 413   return false;
 414 }
 415 










 416 // When to terminate from the termination protocol.
 417 class TerminatorTerminator: public CHeapObj<mtInternal> {
 418 public:
 419   virtual bool should_exit_termination() = 0;
 420 };
 421 
 422 // A class to aid in the termination of a set of parallel tasks using
 423 // TaskQueueSet's for work stealing.
 424 
 425 #undef TRACESPINNING
 426 
 427 class ParallelTaskTerminator: public StackObj {
 428 private:
 429   uint _n_threads;
 430   TaskQueueSetSuper* _queue_set;
 431   volatile uint _offered_termination;
 432 
 433 #ifdef TRACESPINNING
 434   static uint _total_yields;
 435   static uint _total_spins;
 436   static uint _total_peeks;
 437 #endif
 438 
 439   bool peek_in_queue_set();
 440 protected:
 441   virtual void yield();
 442   void sleep(uint millis);
 443 
 444 public:
 445 
 446   // "n_threads" is the number of threads to be terminated.  "queue_set" is a
 447   // queue sets of work queues of other threads.
 448   ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
 449 
 450   // The current thread has no work, and is ready to terminate if everyone
 451   // else is.  If returns "true", all threads are terminated.  If returns
 452   // "false", available work has been observed in one of the task queues,
 453   // so the global task is not complete.
 454   bool offer_termination() {
 455     return offer_termination(NULL);
 456   }
 457 
 458   // As above, but it also terminates if the should_exit_termination()
 459   // method of the terminator parameter returns true. If terminator is
 460   // NULL, then it is ignored.
 461   bool offer_termination(TerminatorTerminator* terminator);
 462 
 463   // Reset the terminator, so that it may be reused again.
 464   // The caller is responsible for ensuring that this is done
 465   // in an MT-safe manner, once the previous round of use of
 466   // the terminator is finished.
 467   void reset_for_reuse();
 468   // Same as above but the number of parallel threads is set to the
 469   // given number.
 470   void reset_for_reuse(uint n_threads);
 471 
 472 #ifdef TRACESPINNING
 473   static uint total_yields() { return _total_yields; }
 474   static uint total_spins() { return _total_spins; }
 475   static uint total_peeks() { return _total_peeks; }
 476   static void print_termination_counts();
 477 #endif
 478 };
 479 
 480 typedef GenericTaskQueue<oop, mtGC>             OopTaskQueue;
 481 typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;




 339   // Attempt to pop from the overflow stack; return true if anything was popped.
 340   inline bool pop_overflow(E& t);
 341 
 342   inline overflow_t* overflow_stack() { return &_overflow_stack; }
 343 
 344   inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
 345   inline bool overflow_empty()  const { return _overflow_stack.is_empty(); }
 346   inline bool is_empty()        const {
 347     return taskqueue_empty() && overflow_empty();
 348   }
 349 
 350 private:
 351   overflow_t _overflow_stack;
 352 };
 353 
 354 class TaskQueueSetSuper {
 355 protected:
 356   static int randomParkAndMiller(int* seed0);
 357 public:
 358   // Returns "true" if some TaskQueue in the set contains a task.
 359   virtual bool   peek() = 0;
 360   virtual size_t tasks() = 0;
 361 };
 362 
 363 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
 364 };
 365 
 366 template<class T, MEMFLAGS F>
 367 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
 368 private:
 369   uint _n;
 370   T** _queues;
 371 
 372 public:
 373   typedef typename T::element_type E;
 374 
 375   GenericTaskQueueSet(int n);
 376   ~GenericTaskQueueSet();
 377 
 378   bool steal_best_of_2(uint queue_num, int* seed, E& t);
 379 
 380   void register_queue(uint i, T* q);
 381 
 382   T* queue(uint n);
 383 
 384   // The thread with queue number "queue_num" (and whose random number seed is
 385   // at "seed") is trying to steal a task from some other queue.  (It may try
 386   // several queues, according to some configuration parameter.)  If some steal
 387   // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
 388   // false.
 389   bool steal(uint queue_num, int* seed, E& t);
 390 
 391   bool peek();
 392   size_t tasks();
 393 
 394   uint size() const { return _n; }
 395 };
 396 
 397 template<class T, MEMFLAGS F> void
 398 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
 399   assert(i < _n, "index out of range.");
 400   _queues[i] = q;
 401 }
 402 
 403 template<class T, MEMFLAGS F> T*
 404 GenericTaskQueueSet<T, F>::queue(uint i) {
 405   return _queues[i];
 406 }
 407 
 408 template<class T, MEMFLAGS F>
 409 bool GenericTaskQueueSet<T, F>::peek() {
 410   // Try all the queues.
 411   for (uint j = 0; j < _n; j++) {
 412     if (_queues[j]->peek())
 413       return true;
 414   }
 415   return false;
 416 }
 417 
 418 template<class T, MEMFLAGS F>
 419 size_t GenericTaskQueueSet<T, F>::tasks() {
 420   size_t n = 0;
 421   for (uint j = 0; j < _n; j++) {
 422     n += _queues[j]->size();
 423   }
 424   return n;
 425 }
 426 
 427 
 428 // When to terminate from the termination protocol.
 429 class TerminatorTerminator: public CHeapObj<mtInternal> {
 430 public:
 431   virtual bool should_exit_termination() = 0;
 432 };
 433 
 434 // A class to aid in the termination of a set of parallel tasks using
 435 // TaskQueueSet's for work stealing.
 436 
 437 #undef TRACESPINNING
 438 
 439 class ParallelTaskTerminator: public StackObj {
 440 protected:
 441   uint _n_threads;
 442   TaskQueueSetSuper* _queue_set;
 443   volatile uint _offered_termination;
 444 
 445 #ifdef TRACESPINNING
 446   static uint _total_yields;
 447   static uint _total_spins;
 448   static uint _total_peeks;
 449 #endif
 450 
 451   bool peek_in_queue_set();
 452 protected:
 453   virtual void yield();
 454   void sleep(uint millis);
 455 
 456 public:
 457 
 458   // "n_threads" is the number of threads to be terminated.  "queue_set" is a
 459   // queue sets of work queues of other threads.
 460   ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
 461 
 462   // The current thread has no work, and is ready to terminate if everyone
 463   // else is.  If returns "true", all threads are terminated.  If returns
 464   // "false", available work has been observed in one of the task queues,
 465   // so the global task is not complete.
 466   bool offer_termination() {
 467     return offer_termination(NULL);
 468   }
 469 
 470   // As above, but it also terminates if the should_exit_termination()
 471   // method of the terminator parameter returns true. If terminator is
 472   // NULL, then it is ignored.
 473   virtual bool offer_termination(TerminatorTerminator* terminator);
 474 
 475   // Reset the terminator, so that it may be reused again.
 476   // The caller is responsible for ensuring that this is done
 477   // in an MT-safe manner, once the previous round of use of
 478   // the terminator is finished.
 479   void reset_for_reuse();
 480   // Same as above but the number of parallel threads is set to the
 481   // given number.
 482   void reset_for_reuse(uint n_threads);
 483 
 484 #ifdef TRACESPINNING
 485   static uint total_yields() { return _total_yields; }
 486   static uint total_spins() { return _total_spins; }
 487   static uint total_peeks() { return _total_peeks; }
 488   static void print_termination_counts();
 489 #endif
 490 };
 491 
 492 typedef GenericTaskQueue<oop, mtGC>             OopTaskQueue;
 493 typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;


< prev index next >