Mercurial > hg > truffle
annotate src/share/vm/utilities/taskqueue.cpp @ 1716:be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode.
Reviewed-by: chrisphi, johnc, poonam
author | ysr |
---|---|
date | Mon, 16 Aug 2010 15:58:42 -0700 |
parents | 5f429ee79634 |
children | 8b10f48633dc |
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 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_taskqueue.cpp.incl" | |
27 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
28 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
29 uint ParallelTaskTerminator::_total_yields = 0; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
30 uint ParallelTaskTerminator::_total_spins = 0; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
31 uint ParallelTaskTerminator::_total_peeks = 0; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
32 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
33 |
1665 | 34 #if TASKQUEUE_STATS |
35 const char * const TaskQueueStats::_names[last_stat_id] = { | |
36 "qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax" | |
37 }; | |
38 | |
1709 | 39 TaskQueueStats & TaskQueueStats::operator +=(const TaskQueueStats & addend) |
40 { | |
41 for (unsigned int i = 0; i < last_stat_id; ++i) { | |
42 _stats[i] += addend._stats[i]; | |
43 } | |
44 return *this; | |
45 } | |
46 | |
1665 | 47 void TaskQueueStats::print_header(unsigned int line, outputStream* const stream, |
48 unsigned int width) | |
49 { | |
50 // Use a width w: 1 <= w <= max_width | |
51 const unsigned int max_width = 40; | |
52 const unsigned int w = MAX2(MIN2(width, max_width), 1U); | |
53 | |
54 if (line == 0) { // spaces equal in width to the header | |
55 const unsigned int hdr_width = w * last_stat_id + last_stat_id - 1; | |
56 stream->print("%*s", hdr_width, " "); | |
57 } else if (line == 1) { // labels | |
58 stream->print("%*s", w, _names[0]); | |
59 for (unsigned int i = 1; i < last_stat_id; ++i) { | |
60 stream->print(" %*s", w, _names[i]); | |
61 } | |
62 } else if (line == 2) { // dashed lines | |
63 char dashes[max_width + 1]; | |
64 memset(dashes, '-', w); | |
65 dashes[w] = '\0'; | |
66 stream->print("%s", dashes); | |
67 for (unsigned int i = 1; i < last_stat_id; ++i) { | |
68 stream->print(" %s", dashes); | |
69 } | |
70 } | |
71 } | |
72 | |
73 void TaskQueueStats::print(outputStream* stream, unsigned int width) const | |
74 { | |
75 #define FMT SIZE_FORMAT_W(*) | |
76 stream->print(FMT, width, _stats[0]); | |
77 for (unsigned int i = 1; i < last_stat_id; ++i) { | |
78 stream->print(" " FMT, width, _stats[i]); | |
79 } | |
80 #undef FMT | |
81 } | |
1709 | 82 |
83 #ifdef ASSERT | |
84 // Invariants which should hold after a TaskQueue has been emptied and is | |
85 // quiescent; they do not hold at arbitrary times. | |
86 void TaskQueueStats::verify() const | |
87 { | |
88 assert(get(push) == get(pop) + get(steal), | |
89 err_msg("push=" SIZE_FORMAT " pop=" SIZE_FORMAT " steal=" SIZE_FORMAT, | |
90 get(push), get(pop), get(steal))); | |
91 assert(get(pop_slow) <= get(pop), | |
92 err_msg("pop_slow=" SIZE_FORMAT " pop=" SIZE_FORMAT, | |
93 get(pop_slow), get(pop))); | |
94 assert(get(steal) <= get(steal_attempt), | |
95 err_msg("steal=" SIZE_FORMAT " steal_attempt=" SIZE_FORMAT, | |
96 get(steal), get(steal_attempt))); | |
97 assert(get(overflow) == 0 || get(push) != 0, | |
98 err_msg("overflow=" SIZE_FORMAT " push=" SIZE_FORMAT, | |
99 get(overflow), get(push))); | |
100 assert(get(overflow_max_len) == 0 || get(overflow) != 0, | |
101 err_msg("overflow_max_len=" SIZE_FORMAT " overflow=" SIZE_FORMAT, | |
102 get(overflow_max_len), get(overflow))); | |
103 } | |
104 #endif // ASSERT | |
1665 | 105 #endif // TASKQUEUE_STATS |
106 | |
0 | 107 int TaskQueueSetSuper::randomParkAndMiller(int *seed0) { |
108 const int a = 16807; | |
109 const int m = 2147483647; | |
110 const int q = 127773; /* m div a */ | |
111 const int r = 2836; /* m mod a */ | |
112 assert(sizeof(int) == 4, "I think this relies on that"); | |
113 int seed = *seed0; | |
114 int hi = seed / q; | |
115 int lo = seed % q; | |
116 int test = a * lo - r * hi; | |
117 if (test > 0) | |
118 seed = test; | |
119 else | |
120 seed = test + m; | |
121 *seed0 = seed; | |
122 return seed; | |
123 } | |
124 | |
125 ParallelTaskTerminator:: | |
126 ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) : | |
127 _n_threads(n_threads), | |
128 _queue_set(queue_set), | |
129 _offered_termination(0) {} | |
130 | |
131 bool ParallelTaskTerminator::peek_in_queue_set() { | |
132 return _queue_set->peek(); | |
133 } | |
134 | |
135 void ParallelTaskTerminator::yield() { | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
136 assert(_offered_termination <= _n_threads, "Invariant"); |
0 | 137 os::yield(); |
138 } | |
139 | |
140 void ParallelTaskTerminator::sleep(uint millis) { | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
141 assert(_offered_termination <= _n_threads, "Invariant"); |
0 | 142 os::sleep(Thread::current(), millis, false); |
143 } | |
144 | |
342 | 145 bool |
146 ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
147 assert(_offered_termination < _n_threads, "Invariant"); |
0 | 148 Atomic::inc(&_offered_termination); |
149 | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
470
diff
changeset
|
150 uint yield_count = 0; |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
151 // Number of hard spin loops done since last yield |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
152 uint hard_spin_count = 0; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
153 // Number of iterations in the hard spin loop. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
154 uint hard_spin_limit = WorkStealingHardSpins; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
155 |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
156 // If WorkStealingSpinToYieldRatio is 0, no hard spinning is done. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
157 // If it is greater than 0, then start with a small number |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
158 // of spins and increase number with each turn at spinning until |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
159 // the count of hard spins exceeds WorkStealingSpinToYieldRatio. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
160 // Then do a yield() call and start spinning afresh. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
161 if (WorkStealingSpinToYieldRatio > 0) { |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
162 hard_spin_limit = WorkStealingHardSpins >> WorkStealingSpinToYieldRatio; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
163 hard_spin_limit = MAX2(hard_spin_limit, 1U); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
164 } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
165 // Remember the initial spin limit. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
166 uint hard_spin_start = hard_spin_limit; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
167 |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
168 // Loop waiting for all threads to offer termination or |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
169 // more work. |
0 | 170 while (true) { |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
171 assert(_offered_termination <= _n_threads, "Invariant"); |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
172 // Are all threads offering termination? |
0 | 173 if (_offered_termination == _n_threads) { |
174 return true; | |
175 } else { | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
176 // Look for more work. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
177 // Periodically sleep() instead of yield() to give threads |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
178 // waiting on the cores the chance to grab this code |
0 | 179 if (yield_count <= WorkStealingYieldsBeforeSleep) { |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
180 // Do a yield or hardspin. For purposes of deciding whether |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
181 // to sleep, count this as a yield. |
0 | 182 yield_count++; |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
183 |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
184 // Periodically call yield() instead spinning |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
185 // After WorkStealingSpinToYieldRatio spins, do a yield() call |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
186 // and reset the counts and starting limit. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
187 if (hard_spin_count > WorkStealingSpinToYieldRatio) { |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
188 yield(); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
189 hard_spin_count = 0; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
190 hard_spin_limit = hard_spin_start; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
191 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
192 _total_yields++; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
193 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
194 } else { |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
195 // Hard spin this time |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
196 // Increase the hard spinning period but only up to a limit. |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
197 hard_spin_limit = MIN2(2*hard_spin_limit, |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
198 (uint) WorkStealingHardSpins); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
199 for (uint j = 0; j < hard_spin_limit; j++) { |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
200 SpinPause(); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
201 } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
202 hard_spin_count++; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
203 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
204 _total_spins++; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
205 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
206 } |
0 | 207 } else { |
208 if (PrintGCDetails && Verbose) { | |
209 gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() " | |
210 "thread %d sleeps after %d yields", | |
211 Thread::current(), yield_count); | |
212 } | |
213 yield_count = 0; | |
214 // A sleep will cause this processor to seek work on another processor's | |
215 // runqueue, if it has nothing else to run (as opposed to the yield | |
216 // which may only move the thread to the end of the this processor's | |
217 // runqueue). | |
218 sleep(WorkStealingSleepMillis); | |
219 } | |
220 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
221 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
222 _total_peeks++; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
223 #endif |
342 | 224 if (peek_in_queue_set() || |
225 (terminator != NULL && terminator->should_exit_termination())) { | |
0 | 226 Atomic::dec(&_offered_termination); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
227 assert(_offered_termination < _n_threads, "Invariant"); |
0 | 228 return false; |
229 } | |
230 } | |
231 } | |
232 } | |
233 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
234 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
235 void ParallelTaskTerminator::print_termination_counts() { |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
236 gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
237 "Total spins: %lld Total peeks: %lld", |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
238 total_yields(), |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
239 total_spins(), |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
240 total_peeks()); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
241 } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
242 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
243 |
0 | 244 void ParallelTaskTerminator::reset_for_reuse() { |
245 if (_offered_termination != 0) { | |
246 assert(_offered_termination == _n_threads, | |
247 "Terminator may still be in use"); | |
248 _offered_termination = 0; | |
249 } | |
250 } | |
251 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
845
diff
changeset
|
252 #ifdef ASSERT |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
845
diff
changeset
|
253 bool ObjArrayTask::is_valid() const { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
845
diff
changeset
|
254 return _obj != NULL && _obj->is_objArray() && _index > 0 && |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
845
diff
changeset
|
255 _index < objArrayOop(_obj)->length(); |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
845
diff
changeset
|
256 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
845
diff
changeset
|
257 #endif // ASSERT |