Mercurial > hg > truffle
annotate src/share/vm/utilities/taskqueue.hpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | b92c45f2bc75 |
rev | line source |
---|---|
0 | 1 /* |
1638 | 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1311
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1311
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1311
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_UTILITIES_TASKQUEUE_HPP |
26 #define SHARE_VM_UTILITIES_TASKQUEUE_HPP | |
27 | |
28 #include "memory/allocation.hpp" | |
29 #include "memory/allocation.inline.hpp" | |
30 #include "runtime/mutex.hpp" | |
31 #include "utilities/stack.hpp" | |
32 #ifdef TARGET_OS_ARCH_linux_x86 | |
33 # include "orderAccess_linux_x86.inline.hpp" | |
34 #endif | |
35 #ifdef TARGET_OS_ARCH_linux_sparc | |
36 # include "orderAccess_linux_sparc.inline.hpp" | |
37 #endif | |
38 #ifdef TARGET_OS_ARCH_linux_zero | |
39 # include "orderAccess_linux_zero.inline.hpp" | |
40 #endif | |
41 #ifdef TARGET_OS_ARCH_solaris_x86 | |
42 # include "orderAccess_solaris_x86.inline.hpp" | |
43 #endif | |
44 #ifdef TARGET_OS_ARCH_solaris_sparc | |
45 # include "orderAccess_solaris_sparc.inline.hpp" | |
46 #endif | |
47 #ifdef TARGET_OS_ARCH_windows_x86 | |
48 # include "orderAccess_windows_x86.inline.hpp" | |
49 #endif | |
50 | |
1665 | 51 // Simple TaskQueue stats that are collected by default in debug builds. |
52 | |
53 #if !defined(TASKQUEUE_STATS) && defined(ASSERT) | |
54 #define TASKQUEUE_STATS 1 | |
55 #elif !defined(TASKQUEUE_STATS) | |
56 #define TASKQUEUE_STATS 0 | |
57 #endif | |
58 | |
59 #if TASKQUEUE_STATS | |
60 #define TASKQUEUE_STATS_ONLY(code) code | |
61 #else | |
62 #define TASKQUEUE_STATS_ONLY(code) | |
63 #endif // TASKQUEUE_STATS | |
64 | |
65 #if TASKQUEUE_STATS | |
66 class TaskQueueStats { | |
67 public: | |
68 enum StatId { | |
69 push, // number of taskqueue pushes | |
70 pop, // number of taskqueue pops | |
71 pop_slow, // subset of taskqueue pops that were done slow-path | |
72 steal_attempt, // number of taskqueue steal attempts | |
73 steal, // number of taskqueue steals | |
74 overflow, // number of overflow pushes | |
75 overflow_max_len, // max length of overflow stack | |
76 last_stat_id | |
77 }; | |
78 | |
79 public: | |
80 inline TaskQueueStats() { reset(); } | |
81 | |
82 inline void record_push() { ++_stats[push]; } | |
83 inline void record_pop() { ++_stats[pop]; } | |
84 inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; } | |
85 inline void record_steal(bool success); | |
86 inline void record_overflow(size_t new_length); | |
87 | |
1709 | 88 TaskQueueStats & operator +=(const TaskQueueStats & addend); |
89 | |
1665 | 90 inline size_t get(StatId id) const { return _stats[id]; } |
91 inline const size_t* get() const { return _stats; } | |
92 | |
93 inline void reset(); | |
94 | |
1709 | 95 // Print the specified line of the header (does not include a line separator). |
1665 | 96 static void print_header(unsigned int line, outputStream* const stream = tty, |
97 unsigned int width = 10); | |
1709 | 98 // Print the statistics (does not include a line separator). |
1665 | 99 void print(outputStream* const stream = tty, unsigned int width = 10) const; |
100 | |
1709 | 101 DEBUG_ONLY(void verify() const;) |
102 | |
1665 | 103 private: |
104 size_t _stats[last_stat_id]; | |
105 static const char * const _names[last_stat_id]; | |
106 }; | |
107 | |
108 void TaskQueueStats::record_steal(bool success) { | |
109 ++_stats[steal_attempt]; | |
110 if (success) ++_stats[steal]; | |
111 } | |
112 | |
113 void TaskQueueStats::record_overflow(size_t new_len) { | |
114 ++_stats[overflow]; | |
115 if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len; | |
116 } | |
117 | |
118 void TaskQueueStats::reset() { | |
119 memset(_stats, 0, sizeof(_stats)); | |
120 } | |
121 #endif // TASKQUEUE_STATS | |
122 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
123 template <unsigned int N> |
0 | 124 class TaskQueueSuper: public CHeapObj { |
125 protected: | |
907 | 126 // Internal type for indexing the queue; also used for the tag. |
127 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t; | |
128 | |
129 // The first free element after the last one pushed (mod N). | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
130 volatile uint _bottom; |
0 | 131 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
132 enum { MOD_N_MASK = N - 1 }; |
907 | 133 |
134 class Age { | |
135 public: | |
136 Age(size_t data = 0) { _data = data; } | |
137 Age(const Age& age) { _data = age._data; } | |
138 Age(idx_t top, idx_t tag) { _fields._top = top; _fields._tag = tag; } | |
0 | 139 |
907 | 140 Age get() const volatile { return _data; } |
141 void set(Age age) volatile { _data = age._data; } | |
142 | |
143 idx_t top() const volatile { return _fields._top; } | |
144 idx_t tag() const volatile { return _fields._tag; } | |
0 | 145 |
907 | 146 // Increment top; if it wraps, increment tag also. |
147 void increment() { | |
148 _fields._top = increment_index(_fields._top); | |
149 if (_fields._top == 0) ++_fields._tag; | |
150 } | |
0 | 151 |
907 | 152 Age cmpxchg(const Age new_age, const Age old_age) volatile { |
153 return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data, | |
154 (volatile intptr_t *)&_data, | |
155 (intptr_t)old_age._data); | |
156 } | |
157 | |
158 bool operator ==(const Age& other) const { return _data == other._data; } | |
0 | 159 |
907 | 160 private: |
161 struct fields { | |
162 idx_t _top; | |
163 idx_t _tag; | |
164 }; | |
165 union { | |
166 size_t _data; | |
167 fields _fields; | |
168 }; | |
0 | 169 }; |
907 | 170 |
171 volatile Age _age; | |
172 | |
173 // These both operate mod N. | |
174 static uint increment_index(uint ind) { | |
175 return (ind + 1) & MOD_N_MASK; | |
0 | 176 } |
907 | 177 static uint decrement_index(uint ind) { |
178 return (ind - 1) & MOD_N_MASK; | |
0 | 179 } |
180 | |
907 | 181 // Returns a number in the range [0..N). If the result is "N-1", it should be |
182 // interpreted as 0. | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
183 uint dirty_size(uint bot, uint top) const { |
907 | 184 return (bot - top) & MOD_N_MASK; |
0 | 185 } |
186 | |
187 // Returns the size corresponding to the given "bot" and "top". | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
188 uint size(uint bot, uint top) const { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
189 uint sz = dirty_size(bot, top); |
907 | 190 // Has the queue "wrapped", so that bottom is less than top? There's a |
191 // complicated special case here. A pair of threads could perform pop_local | |
192 // and pop_global operations concurrently, starting from a state in which | |
193 // _bottom == _top+1. The pop_local could succeed in decrementing _bottom, | |
194 // and the pop_global in incrementing _top (in which case the pop_global | |
195 // will be awarded the contested queue element.) The resulting state must | |
196 // be interpreted as an empty queue. (We only need to worry about one such | |
197 // event: only the queue owner performs pop_local's, and several concurrent | |
198 // threads attempting to perform the pop_global will all perform the same | |
199 // CAS, and only one can succeed.) Any stealing thread that reads after | |
200 // either the increment or decrement will see an empty queue, and will not | |
201 // join the competitors. The "sz == -1 || sz == N-1" state will not be | |
202 // modified by concurrent queues, so the owner thread can reset the state to | |
203 // _bottom == top so subsequent pushes will be performed normally. | |
204 return (sz == N - 1) ? 0 : sz; | |
0 | 205 } |
206 | |
207 public: | |
208 TaskQueueSuper() : _bottom(0), _age() {} | |
209 | |
1638 | 210 // Return true if the TaskQueue contains/does not contain any tasks. |
211 bool peek() const { return _bottom != _age.top(); } | |
212 bool is_empty() const { return size() == 0; } | |
0 | 213 |
214 // Return an estimate of the number of elements in the queue. | |
215 // The "careful" version admits the possibility of pop_local/pop_global | |
216 // races. | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
217 uint size() const { |
907 | 218 return size(_bottom, _age.top()); |
0 | 219 } |
220 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
221 uint dirty_size() const { |
907 | 222 return dirty_size(_bottom, _age.top()); |
0 | 223 } |
224 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
225 void set_empty() { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
226 _bottom = 0; |
907 | 227 _age.set(0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
228 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
229 |
0 | 230 // Maximum number of elements allowed in the queue. This is two less |
231 // than the actual queue size, for somewhat complicated reasons. | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
232 uint max_elems() const { return N - 2; } |
1284 | 233 |
234 // Total size of queue. | |
235 static const uint total_size() { return N; } | |
1665 | 236 |
237 TASKQUEUE_STATS_ONLY(TaskQueueStats stats;) | |
0 | 238 }; |
239 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
240 template<class E, unsigned int N = TASKQUEUE_SIZE> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
241 class GenericTaskQueue: public TaskQueueSuper<N> { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
242 protected: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
243 typedef typename TaskQueueSuper<N>::Age Age; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
244 typedef typename TaskQueueSuper<N>::idx_t idx_t; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
245 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
246 using TaskQueueSuper<N>::_bottom; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
247 using TaskQueueSuper<N>::_age; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
248 using TaskQueueSuper<N>::increment_index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
249 using TaskQueueSuper<N>::decrement_index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
250 using TaskQueueSuper<N>::dirty_size; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
251 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
252 public: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
253 using TaskQueueSuper<N>::max_elems; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
254 using TaskQueueSuper<N>::size; |
1665 | 255 TASKQUEUE_STATS_ONLY(using TaskQueueSuper<N>::stats;) |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
256 |
0 | 257 private: |
258 // Slow paths for push, pop_local. (pop_global has no fast path.) | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
259 bool push_slow(E t, uint dirty_n_elems); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
260 bool pop_local_slow(uint localBot, Age oldAge); |
0 | 261 |
262 public: | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
263 typedef E element_type; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
264 |
0 | 265 // Initializes the queue to empty. |
266 GenericTaskQueue(); | |
267 | |
268 void initialize(); | |
269 | |
1638 | 270 // Push the task "t" on the queue. Returns "false" iff the queue is full. |
0 | 271 inline bool push(E t); |
272 | |
1638 | 273 // Attempts to claim a task from the "local" end of the queue (the most |
274 // recently pushed). If successful, returns true and sets t to the task; | |
275 // otherwise, returns false (the queue is empty). | |
0 | 276 inline bool pop_local(E& t); |
277 | |
1638 | 278 // Like pop_local(), but uses the "global" end of the queue (the least |
279 // recently pushed). | |
0 | 280 bool pop_global(E& t); |
281 | |
282 // Delete any resource associated with the queue. | |
283 ~GenericTaskQueue(); | |
284 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
285 // apply the closure to all elements in the task queue |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
286 void oops_do(OopClosure* f); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
287 |
0 | 288 private: |
289 // Element array. | |
290 volatile E* _elems; | |
291 }; | |
292 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
293 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
294 GenericTaskQueue<E, N>::GenericTaskQueue() { |
907 | 295 assert(sizeof(Age) == sizeof(size_t), "Depends on this."); |
0 | 296 } |
297 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
298 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
299 void GenericTaskQueue<E, N>::initialize() { |
907 | 300 _elems = NEW_C_HEAP_ARRAY(E, N); |
0 | 301 } |
302 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
303 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
304 void GenericTaskQueue<E, N>::oops_do(OopClosure* f) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
305 // tty->print_cr("START OopTaskQueue::oops_do"); |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
306 uint iters = size(); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
307 uint index = _bottom; |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
308 for (uint i = 0; i < iters; ++i) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
309 index = decrement_index(index); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
310 // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
311 // index, &_elems[index], _elems[index]); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
312 E* t = (E*)&_elems[index]; // cast away volatility |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
313 oop* p = (oop*)t; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
314 assert((*t)->is_oop_or_null(), "Not an oop or null"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
315 f->do_oop(p); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
316 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
317 // tty->print_cr("END OopTaskQueue::oops_do"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
318 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
319 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
320 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
321 bool GenericTaskQueue<E, N>::push_slow(E t, uint dirty_n_elems) { |
907 | 322 if (dirty_n_elems == N - 1) { |
0 | 323 // Actually means 0, so do the push. |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
324 uint localBot = _bottom; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
325 // g++ complains if the volatile result of the assignment is unused. |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
326 const_cast<E&>(_elems[localBot] = t); |
1024
2c03ce058f55
6888847: TaskQueue needs release_store() for correctness on RMO machines
bobv
parents:
907
diff
changeset
|
327 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
1665 | 328 TASKQUEUE_STATS_ONLY(stats.record_push()); |
0 | 329 return true; |
907 | 330 } |
331 return false; | |
0 | 332 } |
333 | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
334 // pop_local_slow() is done by the owning thread and is trying to |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
335 // get the last task in the queue. It will compete with pop_global() |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
336 // that will be used by other threads. The tag age is incremented |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
337 // whenever the queue goes empty which it will do here if this thread |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
338 // gets the last task or in pop_global() if the queue wraps (top == 0 |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
339 // and pop_global() succeeds, see pop_global()). |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
340 template<class E, unsigned int N> |
1665 | 341 bool GenericTaskQueue<E, N>::pop_local_slow(uint localBot, Age oldAge) { |
0 | 342 // This queue was observed to contain exactly one element; either this |
343 // thread will claim it, or a competing "pop_global". In either case, | |
344 // the queue will be logically empty afterwards. Create a new Age value | |
345 // that represents the empty queue for the given value of "_bottom". (We | |
346 // must also increment "tag" because of the case where "bottom == 1", | |
347 // "top == 0". A pop_global could read the queue element in that case, | |
348 // then have the owner thread do a pop followed by another push. Without | |
349 // the incrementing of "tag", the pop_global's CAS could succeed, | |
350 // allowing it to believe it has claimed the stale element.) | |
907 | 351 Age newAge((idx_t)localBot, oldAge.tag() + 1); |
0 | 352 // Perhaps a competing pop_global has already incremented "top", in which |
353 // case it wins the element. | |
354 if (localBot == oldAge.top()) { | |
355 // No competing pop_global has yet incremented "top"; we'll try to | |
356 // install new_age, thus claiming the element. | |
907 | 357 Age tempAge = _age.cmpxchg(newAge, oldAge); |
0 | 358 if (tempAge == oldAge) { |
359 // We win. | |
907 | 360 assert(dirty_size(localBot, _age.top()) != N - 1, "sanity"); |
1665 | 361 TASKQUEUE_STATS_ONLY(stats.record_pop_slow()); |
0 | 362 return true; |
363 } | |
364 } | |
907 | 365 // We lose; a completing pop_global gets the element. But the queue is empty |
366 // and top is greater than bottom. Fix this representation of the empty queue | |
367 // to become the canonical one. | |
368 _age.set(newAge); | |
369 assert(dirty_size(localBot, _age.top()) != N - 1, "sanity"); | |
0 | 370 return false; |
371 } | |
372 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
373 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
374 bool GenericTaskQueue<E, N>::pop_global(E& t) { |
907 | 375 Age oldAge = _age.get(); |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
376 uint localBot = _bottom; |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
377 uint n_elems = size(localBot, oldAge.top()); |
0 | 378 if (n_elems == 0) { |
379 return false; | |
380 } | |
907 | 381 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
382 const_cast<E&>(t = _elems[oldAge.top()]); |
907 | 383 Age newAge(oldAge); |
384 newAge.increment(); | |
385 Age resAge = _age.cmpxchg(newAge, oldAge); | |
386 | |
0 | 387 // Note that using "_bottom" here might fail, since a pop_local might |
388 // have decremented it. | |
907 | 389 assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity"); |
390 return resAge == oldAge; | |
0 | 391 } |
392 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
393 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
394 GenericTaskQueue<E, N>::~GenericTaskQueue() { |
0 | 395 FREE_C_HEAP_ARRAY(E, _elems); |
396 } | |
397 | |
1638 | 398 // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for |
399 // elements that do not fit in the TaskQueue. | |
400 // | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
401 // This class hides two methods from super classes: |
1638 | 402 // |
403 // push() - push onto the task queue or, if that fails, onto the overflow stack | |
404 // is_empty() - return true if both the TaskQueue and overflow stack are empty | |
405 // | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
406 // Note that size() is not hidden--it returns the number of elements in the |
1638 | 407 // TaskQueue, and does not include the size of the overflow stack. This |
408 // simplifies replacement of GenericTaskQueues with OverflowTaskQueues. | |
409 template<class E, unsigned int N = TASKQUEUE_SIZE> | |
410 class OverflowTaskQueue: public GenericTaskQueue<E, N> | |
411 { | |
412 public: | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
413 typedef Stack<E> overflow_t; |
1638 | 414 typedef GenericTaskQueue<E, N> taskqueue_t; |
415 | |
1665 | 416 TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;) |
417 | |
1638 | 418 // Push task t onto the queue or onto the overflow stack. Return true. |
419 inline bool push(E t); | |
420 | |
421 // Attempt to pop from the overflow stack; return true if anything was popped. | |
422 inline bool pop_overflow(E& t); | |
423 | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
424 inline overflow_t* overflow_stack() { return &_overflow_stack; } |
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
425 |
1638 | 426 inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); } |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
427 inline bool overflow_empty() const { return _overflow_stack.is_empty(); } |
1638 | 428 inline bool is_empty() const { |
429 return taskqueue_empty() && overflow_empty(); | |
430 } | |
431 | |
432 private: | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
433 overflow_t _overflow_stack; |
1638 | 434 }; |
435 | |
436 template <class E, unsigned int N> | |
437 bool OverflowTaskQueue<E, N>::push(E t) | |
438 { | |
439 if (!taskqueue_t::push(t)) { | |
440 overflow_stack()->push(t); | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1833
diff
changeset
|
441 TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size())); |
1638 | 442 } |
443 return true; | |
444 } | |
445 | |
446 template <class E, unsigned int N> | |
447 bool OverflowTaskQueue<E, N>::pop_overflow(E& t) | |
448 { | |
449 if (overflow_empty()) return false; | |
450 t = overflow_stack()->pop(); | |
451 return true; | |
452 } | |
453 | |
0 | 454 class TaskQueueSetSuper: public CHeapObj { |
455 protected: | |
456 static int randomParkAndMiller(int* seed0); | |
457 public: | |
458 // Returns "true" if some TaskQueue in the set contains a task. | |
459 virtual bool peek() = 0; | |
460 }; | |
461 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
462 template<class T> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
463 class GenericTaskQueueSet: public TaskQueueSetSuper { |
0 | 464 private: |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
465 uint _n; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
466 T** _queues; |
0 | 467 |
468 public: | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
469 typedef typename T::element_type E; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
470 |
0 | 471 GenericTaskQueueSet(int n) : _n(n) { |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
472 typedef T* GenericTaskQueuePtr; |
0 | 473 _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n); |
474 for (int i = 0; i < n; i++) { | |
475 _queues[i] = NULL; | |
476 } | |
477 } | |
478 | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
479 bool steal_1_random(uint queue_num, int* seed, E& t); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
480 bool steal_best_of_2(uint queue_num, int* seed, E& t); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
481 bool steal_best_of_all(uint queue_num, int* seed, E& t); |
0 | 482 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
483 void register_queue(uint i, T* q); |
0 | 484 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
485 T* queue(uint n); |
0 | 486 |
1638 | 487 // The thread with queue number "queue_num" (and whose random number seed is |
488 // at "seed") is trying to steal a task from some other queue. (It may try | |
489 // several queues, according to some configuration parameter.) If some steal | |
490 // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns | |
491 // false. | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
492 bool steal(uint queue_num, int* seed, E& t); |
0 | 493 |
494 bool peek(); | |
495 }; | |
496 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
497 template<class T> void |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
498 GenericTaskQueueSet<T>::register_queue(uint i, T* q) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
499 assert(i < _n, "index out of range."); |
0 | 500 _queues[i] = q; |
501 } | |
502 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
503 template<class T> T* |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
504 GenericTaskQueueSet<T>::queue(uint i) { |
0 | 505 return _queues[i]; |
506 } | |
507 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
508 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
509 GenericTaskQueueSet<T>::steal(uint queue_num, int* seed, E& t) { |
1665 | 510 for (uint i = 0; i < 2 * _n; i++) { |
511 if (steal_best_of_2(queue_num, seed, t)) { | |
512 TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true)); | |
0 | 513 return true; |
1665 | 514 } |
515 } | |
516 TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false)); | |
0 | 517 return false; |
518 } | |
519 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
520 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
521 GenericTaskQueueSet<T>::steal_best_of_all(uint queue_num, int* seed, E& t) { |
0 | 522 if (_n > 2) { |
523 int best_k; | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
524 uint best_sz = 0; |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
525 for (uint k = 0; k < _n; k++) { |
0 | 526 if (k == queue_num) continue; |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
527 uint sz = _queues[k]->size(); |
0 | 528 if (sz > best_sz) { |
529 best_sz = sz; | |
530 best_k = k; | |
531 } | |
532 } | |
533 return best_sz > 0 && _queues[best_k]->pop_global(t); | |
534 } else if (_n == 2) { | |
535 // Just try the other one. | |
536 int k = (queue_num + 1) % 2; | |
537 return _queues[k]->pop_global(t); | |
538 } else { | |
539 assert(_n == 1, "can't be zero."); | |
540 return false; | |
541 } | |
542 } | |
543 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
544 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
545 GenericTaskQueueSet<T>::steal_1_random(uint queue_num, int* seed, E& t) { |
0 | 546 if (_n > 2) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
547 uint k = queue_num; |
0 | 548 while (k == queue_num) k = randomParkAndMiller(seed) % _n; |
549 return _queues[2]->pop_global(t); | |
550 } else if (_n == 2) { | |
551 // Just try the other one. | |
552 int k = (queue_num + 1) % 2; | |
553 return _queues[k]->pop_global(t); | |
554 } else { | |
555 assert(_n == 1, "can't be zero."); | |
556 return false; | |
557 } | |
558 } | |
559 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
560 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
561 GenericTaskQueueSet<T>::steal_best_of_2(uint queue_num, int* seed, E& t) { |
0 | 562 if (_n > 2) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
563 uint k1 = queue_num; |
0 | 564 while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
565 uint k2 = queue_num; |
0 | 566 while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; |
567 // Sample both and try the larger. | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
568 uint sz1 = _queues[k1]->size(); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
569 uint sz2 = _queues[k2]->size(); |
0 | 570 if (sz2 > sz1) return _queues[k2]->pop_global(t); |
571 else return _queues[k1]->pop_global(t); | |
572 } else if (_n == 2) { | |
573 // Just try the other one. | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
574 uint k = (queue_num + 1) % 2; |
0 | 575 return _queues[k]->pop_global(t); |
576 } else { | |
577 assert(_n == 1, "can't be zero."); | |
578 return false; | |
579 } | |
580 } | |
581 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
582 template<class T> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
583 bool GenericTaskQueueSet<T>::peek() { |
0 | 584 // Try all the queues. |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
585 for (uint j = 0; j < _n; j++) { |
0 | 586 if (_queues[j]->peek()) |
587 return true; | |
588 } | |
589 return false; | |
590 } | |
591 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
592 // When to terminate from the termination protocol. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
593 class TerminatorTerminator: public CHeapObj { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
594 public: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
595 virtual bool should_exit_termination() = 0; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
596 }; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
597 |
0 | 598 // A class to aid in the termination of a set of parallel tasks using |
599 // TaskQueueSet's for work stealing. | |
600 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
601 #undef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
602 |
0 | 603 class ParallelTaskTerminator: public StackObj { |
604 private: | |
605 int _n_threads; | |
606 TaskQueueSetSuper* _queue_set; | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
607 int _offered_termination; |
0 | 608 |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
609 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
610 static uint _total_yields; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
611 static uint _total_spins; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
612 static uint _total_peeks; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
613 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
614 |
0 | 615 bool peek_in_queue_set(); |
616 protected: | |
617 virtual void yield(); | |
618 void sleep(uint millis); | |
619 | |
620 public: | |
621 | |
622 // "n_threads" is the number of threads to be terminated. "queue_set" is a | |
623 // queue sets of work queues of other threads. | |
624 ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set); | |
625 | |
626 // The current thread has no work, and is ready to terminate if everyone | |
627 // else is. If returns "true", all threads are terminated. If returns | |
628 // "false", available work has been observed in one of the task queues, | |
629 // so the global task is not complete. | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
630 bool offer_termination() { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
631 return offer_termination(NULL); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
632 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
633 |
907 | 634 // As above, but it also terminates if the should_exit_termination() |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
635 // method of the terminator parameter returns true. If terminator is |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
636 // NULL, then it is ignored. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
637 bool offer_termination(TerminatorTerminator* terminator); |
0 | 638 |
639 // Reset the terminator, so that it may be reused again. | |
640 // The caller is responsible for ensuring that this is done | |
641 // in an MT-safe manner, once the previous round of use of | |
642 // the terminator is finished. | |
643 void reset_for_reuse(); | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
644 // Same as above but the number of parallel threads is set to the |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
645 // given number. |
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
646 void reset_for_reuse(int n_threads); |
0 | 647 |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
648 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
649 static uint total_yields() { return _total_yields; } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
650 static uint total_spins() { return _total_spins; } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
651 static uint total_peeks() { return _total_peeks; } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
652 static void print_termination_counts(); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
653 #endif |
0 | 654 }; |
655 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
656 template<class E, unsigned int N> inline bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
657 GenericTaskQueue<E, N>::push(E t) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
658 uint localBot = _bottom; |
907 | 659 assert((localBot >= 0) && (localBot < N), "_bottom out of range."); |
660 idx_t top = _age.top(); | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
661 uint dirty_n_elems = dirty_size(localBot, top); |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
662 assert(dirty_n_elems < N, "n_elems out of range."); |
0 | 663 if (dirty_n_elems < max_elems()) { |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
664 // g++ complains if the volatile result of the assignment is unused. |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
665 const_cast<E&>(_elems[localBot] = t); |
1024
2c03ce058f55
6888847: TaskQueue needs release_store() for correctness on RMO machines
bobv
parents:
907
diff
changeset
|
666 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
1665 | 667 TASKQUEUE_STATS_ONLY(stats.record_push()); |
0 | 668 return true; |
669 } else { | |
670 return push_slow(t, dirty_n_elems); | |
671 } | |
672 } | |
673 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
674 template<class E, unsigned int N> inline bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
675 GenericTaskQueue<E, N>::pop_local(E& t) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
676 uint localBot = _bottom; |
907 | 677 // This value cannot be N-1. That can only occur as a result of |
0 | 678 // the assignment to bottom in this method. If it does, this method |
1638 | 679 // resets the size to 0 before the next call (which is sequential, |
0 | 680 // since this is pop_local.) |
907 | 681 uint dirty_n_elems = dirty_size(localBot, _age.top()); |
682 assert(dirty_n_elems != N - 1, "Shouldn't be possible..."); | |
0 | 683 if (dirty_n_elems == 0) return false; |
684 localBot = decrement_index(localBot); | |
685 _bottom = localBot; | |
686 // This is necessary to prevent any read below from being reordered | |
687 // before the store just above. | |
688 OrderAccess::fence(); | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
689 const_cast<E&>(t = _elems[localBot]); |
0 | 690 // This is a second read of "age"; the "size()" above is the first. |
691 // If there's still at least one element in the queue, based on the | |
692 // "_bottom" and "age" we've read, then there can be no interference with | |
693 // a "pop_global" operation, and we're done. | |
907 | 694 idx_t tp = _age.top(); // XXX |
0 | 695 if (size(localBot, tp) > 0) { |
907 | 696 assert(dirty_size(localBot, tp) != N - 1, "sanity"); |
1665 | 697 TASKQUEUE_STATS_ONLY(stats.record_pop()); |
0 | 698 return true; |
699 } else { | |
700 // Otherwise, the queue contained exactly one element; we take the slow | |
701 // path. | |
907 | 702 return pop_local_slow(localBot, _age.get()); |
0 | 703 } |
704 } | |
705 | |
1638 | 706 typedef GenericTaskQueue<oop> OopTaskQueue; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
707 typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet; |
0 | 708 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
709 #ifdef _MSC_VER |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
710 #pragma warning(push) |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
711 // warning C4522: multiple assignment operators specified |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
712 #pragma warning(disable:4522) |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
713 #endif |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
714 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
715 // This is a container class for either an oop* or a narrowOop*. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
716 // Both are pushed onto a task queue and the consumer will test is_narrow() |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
717 // to determine which should be processed. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
718 class StarTask { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
719 void* _holder; // either union oop* or narrowOop* |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
720 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
721 enum { COMPRESSED_OOP_MASK = 1 }; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
722 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
723 public: |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
724 StarTask(narrowOop* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
725 assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
726 _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
727 } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
728 StarTask(oop* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
729 assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
730 _holder = (void*)p; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
731 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
732 StarTask() { _holder = NULL; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
733 operator oop*() { return (oop*)_holder; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
734 operator narrowOop*() { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
735 return (narrowOop*)((uintptr_t)_holder & ~COMPRESSED_OOP_MASK); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
736 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
737 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
738 StarTask& operator=(const StarTask& t) { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
739 _holder = t._holder; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
740 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
741 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
742 volatile StarTask& operator=(const volatile StarTask& t) volatile { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
743 _holder = t._holder; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
744 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
745 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
746 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
747 bool is_narrow() const { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
748 return (((uintptr_t)_holder & COMPRESSED_OOP_MASK) != 0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
749 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
750 }; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
751 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
752 class ObjArrayTask |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
753 { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
754 public: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
755 ObjArrayTask(oop o = NULL, int idx = 0): _obj(o), _index(idx) { } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
756 ObjArrayTask(oop o, size_t idx): _obj(o), _index(int(idx)) { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
757 assert(idx <= size_t(max_jint), "too big"); |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
758 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
759 ObjArrayTask(const ObjArrayTask& t): _obj(t._obj), _index(t._index) { } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
760 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
761 ObjArrayTask& operator =(const ObjArrayTask& t) { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
762 _obj = t._obj; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
763 _index = t._index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
764 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
765 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
766 volatile ObjArrayTask& |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
767 operator =(const volatile ObjArrayTask& t) volatile { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
768 _obj = t._obj; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
769 _index = t._index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
770 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
771 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
772 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
773 inline oop obj() const { return _obj; } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
774 inline int index() const { return _index; } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
775 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
776 DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid. |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
777 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
778 private: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
779 oop _obj; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
780 int _index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
781 }; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
782 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
783 #ifdef _MSC_VER |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
784 #pragma warning(pop) |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
785 #endif |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
786 |
1638 | 787 typedef OverflowTaskQueue<StarTask> OopStarTaskQueue; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
788 typedef GenericTaskQueueSet<OopStarTaskQueue> OopStarTaskQueueSet; |
0 | 789 |
1638 | 790 typedef OverflowTaskQueue<size_t> RegionTaskQueue; |
791 typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet; | |
1833
8b10f48633dc
6984287: Regularize how GC parallel workers are specified.
jmasa
parents:
1709
diff
changeset
|
792 |
1972 | 793 |
794 #endif // SHARE_VM_UTILITIES_TASKQUEUE_HPP |