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. |
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 }; |