src/hotspot/share/gc/shared/taskqueue.hpp
changeset 51292 0538a5cdb474
parent 50953 0fad17c646c9
child 52122 cb20bf10cfbd
equal deleted inserted replaced
51291:57aa80913140 51292:0538a5cdb474
    24 
    24 
    25 #ifndef SHARE_VM_GC_SHARED_TASKQUEUE_HPP
    25 #ifndef SHARE_VM_GC_SHARED_TASKQUEUE_HPP
    26 #define SHARE_VM_GC_SHARED_TASKQUEUE_HPP
    26 #define SHARE_VM_GC_SHARED_TASKQUEUE_HPP
    27 
    27 
    28 #include "memory/allocation.hpp"
    28 #include "memory/allocation.hpp"
       
    29 #include "memory/padded.hpp"
    29 #include "oops/oopsHierarchy.hpp"
    30 #include "oops/oopsHierarchy.hpp"
    30 #include "utilities/ostream.hpp"
    31 #include "utilities/ostream.hpp"
    31 #include "utilities/stack.hpp"
    32 #include "utilities/stack.hpp"
    32 
    33 
    33 // Simple TaskQueue stats that are collected by default in debug builds.
    34 // Simple TaskQueue stats that are collected by default in debug builds.
   296   // Apply fn to each element in the task queue.  The queue must not
   297   // Apply fn to each element in the task queue.  The queue must not
   297   // be modified while iterating.
   298   // be modified while iterating.
   298   template<typename Fn> void iterate(Fn fn);
   299   template<typename Fn> void iterate(Fn fn);
   299 
   300 
   300 private:
   301 private:
       
   302   DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);
   301   // Element array.
   303   // Element array.
   302   volatile E* _elems;
   304   volatile E* _elems;
       
   305 
       
   306   DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(E*));
       
   307   // Queue owner local variables. Not to be accessed by other threads.
       
   308 
       
   309   static const uint InvalidQueueId = uint(-1);
       
   310   uint _last_stolen_queue_id; // The id of the queue we last stole from
       
   311 
       
   312   int _seed; // Current random seed used for selecting a random queue during stealing.
       
   313 
       
   314   DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(uint) + sizeof(int));
       
   315 public:
       
   316   int next_random_queue_id();
       
   317 
       
   318   void set_last_stolen_queue_id(uint id)     { _last_stolen_queue_id = id; }
       
   319   uint last_stolen_queue_id() const          { return _last_stolen_queue_id; }
       
   320   bool is_last_stolen_queue_id_valid() const { return _last_stolen_queue_id != InvalidQueueId; }
       
   321   void invalidate_last_stolen_queue_id()     { _last_stolen_queue_id = InvalidQueueId; }
   303 };
   322 };
   304 
   323 
   305 template<class E, MEMFLAGS F, unsigned int N>
   324 template<class E, MEMFLAGS F, unsigned int N>
   306 GenericTaskQueue<E, F, N>::GenericTaskQueue() {
   325 GenericTaskQueue<E, F, N>::GenericTaskQueue() : _last_stolen_queue_id(InvalidQueueId), _seed(17 /* random number */) {
   307   assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
   326   assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
   308 }
   327 }
   309 
   328 
   310 // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
   329 // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
   311 // elements that do not fit in the TaskQueue.
   330 // elements that do not fit in the TaskQueue.
   346 private:
   365 private:
   347   overflow_t _overflow_stack;
   366   overflow_t _overflow_stack;
   348 };
   367 };
   349 
   368 
   350 class TaskQueueSetSuper {
   369 class TaskQueueSetSuper {
   351 protected:
       
   352   static int randomParkAndMiller(int* seed0);
       
   353 public:
   370 public:
   354   // Returns "true" if some TaskQueue in the set contains a task.
   371   // Returns "true" if some TaskQueue in the set contains a task.
   355   virtual bool peek() = 0;
   372   virtual bool peek() = 0;
   356 };
   373 };
   357 
   374 
   365 
   382 
   366 private:
   383 private:
   367   uint _n;
   384   uint _n;
   368   T** _queues;
   385   T** _queues;
   369 
   386 
   370   bool steal_best_of_2(uint queue_num, int* seed, E& t);
   387   bool steal_best_of_2(uint queue_num, E& t);
   371 
   388 
   372 public:
   389 public:
   373   GenericTaskQueueSet(int n);
   390   GenericTaskQueueSet(uint n);
   374   ~GenericTaskQueueSet();
   391   ~GenericTaskQueueSet();
   375 
   392 
   376   void register_queue(uint i, T* q);
   393   void register_queue(uint i, T* q);
   377 
   394 
   378   T* queue(uint n);
   395   T* queue(uint n);
   379 
   396 
   380   // The thread with queue number "queue_num" (and whose random number seed is
   397   // Try to steal a task from some other queue than queue_num. It may perform several attempts at doing so.
   381   // at "seed") is trying to steal a task from some other queue.  (It may try
   398   // Returns if stealing succeeds, and sets "t" to the stolen task.
   382   // several queues, according to some configuration parameter.)  If some steal
   399   bool steal(uint queue_num, E& t);
   383   // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
       
   384   // false.
       
   385   bool steal(uint queue_num, int* seed, E& t);
       
   386 
   400 
   387   bool peek();
   401   bool peek();
   388 
   402 
   389   uint size() const { return _n; }
   403   uint size() const { return _n; }
   390 };
   404 };