47 #if TASKQUEUE_STATS
48 class TaskQueueStats {
49 public:
50 enum StatId {
51 push, // number of taskqueue pushes
52 pop, // number of taskqueue pops
53 pop_slow, // subset of taskqueue pops that were done slow-path
54 steal_attempt, // number of taskqueue steal attempts
55 steal, // number of taskqueue steals
56 overflow, // number of overflow pushes
57 overflow_max_len, // max length of overflow stack
58 last_stat_id
59 };
60
61 public:
62 inline TaskQueueStats() { reset(); }
63
64 inline void record_push() { ++_stats[push]; }
65 inline void record_pop() { ++_stats[pop]; }
66 inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; }
67 inline void record_steal(bool success);
68 inline void record_overflow(size_t new_length);
69
70 TaskQueueStats & operator +=(const TaskQueueStats & addend);
71
72 inline size_t get(StatId id) const { return _stats[id]; }
73 inline const size_t* get() const { return _stats; }
74
75 inline void reset();
76
77 // Print the specified line of the header (does not include a line separator).
78 static void print_header(unsigned int line, outputStream* const stream = tty,
79 unsigned int width = 10);
80 // Print the statistics (does not include a line separator).
81 void print(outputStream* const stream = tty, unsigned int width = 10) const;
82
83 DEBUG_ONLY(void verify() const;)
84
85 private:
86 size_t _stats[last_stat_id];
87 static const char * const _names[last_stat_id];
88 };
89
90 void TaskQueueStats::record_steal(bool success) {
91 ++_stats[steal_attempt];
92 if (success) ++_stats[steal];
93 }
94
95 void TaskQueueStats::record_overflow(size_t new_len) {
96 ++_stats[overflow];
97 if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len;
98 }
99
100 void TaskQueueStats::reset() {
101 memset(_stats, 0, sizeof(_stats));
102 }
103 #endif // TASKQUEUE_STATS
104
105 // TaskQueueSuper collects functionality common to all GenericTaskQueue instances.
106
107 template <unsigned int N, MEMFLAGS F>
108 class TaskQueueSuper: public CHeapObj<F> {
109 protected:
110 // Internal type for indexing the queue; also used for the tag.
111 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t;
112
113 // The first free element after the last one pushed (mod N).
114 volatile uint _bottom;
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.");
|
47 #if TASKQUEUE_STATS
48 class TaskQueueStats {
49 public:
50 enum StatId {
51 push, // number of taskqueue pushes
52 pop, // number of taskqueue pops
53 pop_slow, // subset of taskqueue pops that were done slow-path
54 steal_attempt, // number of taskqueue steal attempts
55 steal, // number of taskqueue steals
56 overflow, // number of overflow pushes
57 overflow_max_len, // max length of overflow stack
58 last_stat_id
59 };
60
61 public:
62 inline TaskQueueStats() { reset(); }
63
64 inline void record_push() { ++_stats[push]; }
65 inline void record_pop() { ++_stats[pop]; }
66 inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; }
67 inline void record_steal_attempt() { ++_stats[steal_attempt]; }
68 inline void record_steal() { ++_stats[steal]; }
69 inline void record_overflow(size_t new_length);
70
71 TaskQueueStats & operator +=(const TaskQueueStats & addend);
72
73 inline size_t get(StatId id) const { return _stats[id]; }
74 inline const size_t* get() const { return _stats; }
75
76 inline void reset();
77
78 // Print the specified line of the header (does not include a line separator).
79 static void print_header(unsigned int line, outputStream* const stream = tty,
80 unsigned int width = 10);
81 // Print the statistics (does not include a line separator).
82 void print(outputStream* const stream = tty, unsigned int width = 10) const;
83
84 DEBUG_ONLY(void verify() const;)
85
86 private:
87 size_t _stats[last_stat_id];
88 static const char * const _names[last_stat_id];
89 };
90
91 void TaskQueueStats::record_overflow(size_t new_len) {
92 ++_stats[overflow];
93 if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len;
94 }
95
96 void TaskQueueStats::reset() {
97 memset(_stats, 0, sizeof(_stats));
98 }
99 #endif // TASKQUEUE_STATS
100
101 // TaskQueueSuper collects functionality common to all GenericTaskQueue instances.
102
103 template <unsigned int N, MEMFLAGS F>
104 class TaskQueueSuper: public CHeapObj<F> {
105 protected:
106 // Internal type for indexing the queue; also used for the tag.
107 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t;
108
109 // The first free element after the last one pushed (mod N).
110 volatile uint _bottom;
343 return taskqueue_empty() && overflow_empty();
344 }
345
346 private:
347 overflow_t _overflow_stack;
348 };
349
350 class TaskQueueSetSuper {
351 protected:
352 static int randomParkAndMiller(int* seed0);
353 public:
354 // Returns "true" if some TaskQueue in the set contains a task.
355 virtual bool peek() = 0;
356 };
357
358 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
359 };
360
361 template<class T, MEMFLAGS F>
362 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
363 public:
364 typedef typename T::element_type E;
365
366 private:
367 uint _n;
368 T** _queues;
369
370 bool steal_best_of_2(uint queue_num, int* seed, E& t);
371
372 public:
373 GenericTaskQueueSet(int n);
374 ~GenericTaskQueueSet();
375
376 void register_queue(uint i, T* q);
377
378 T* queue(uint n);
379
380 // The thread with queue number "queue_num" (and whose random number seed is
381 // at "seed") is trying to steal a task from some other queue. (It may try
382 // several queues, according to some configuration parameter.) If some steal
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
387 bool peek();
388
389 uint size() const { return _n; }
390 };
391
392 template<class T, MEMFLAGS F> void
393 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
394 assert(i < _n, "index out of range.");
|