Mercurial > hg > graal-compiler
annotate src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.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 | c18cbe5936b8 |
children | cd3ef3fd20dd |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2001, 2006, 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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_concurrentMarkSweepThread.cpp.incl" | |
27 | |
28 // ======= Concurrent Mark Sweep Thread ======== | |
29 | |
30 // The CMS thread is created when Concurrent Mark Sweep is used in the | |
31 // older of two generations in a generational memory system. | |
32 | |
33 ConcurrentMarkSweepThread* | |
34 ConcurrentMarkSweepThread::_cmst = NULL; | |
35 CMSCollector* ConcurrentMarkSweepThread::_collector = NULL; | |
36 bool ConcurrentMarkSweepThread::_should_terminate = false; | |
37 int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil; | |
38 | |
39 volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; | |
40 volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0; | |
41 | |
42 volatile bool ConcurrentMarkSweepThread::_icms_enabled = false; | |
43 volatile bool ConcurrentMarkSweepThread::_should_run = false; | |
44 // When icms is enabled, the icms thread is stopped until explicitly | |
45 // started. | |
46 volatile bool ConcurrentMarkSweepThread::_should_stop = true; | |
47 | |
48 SurrogateLockerThread* | |
49 ConcurrentMarkSweepThread::_slt = NULL; | |
50 SurrogateLockerThread::SLT_msg_type | |
51 ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty; | |
52 Monitor* | |
53 ConcurrentMarkSweepThread::_sltMonitor = NULL; | |
54 | |
55 ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) | |
56 : ConcurrentGCThread() { | |
57 assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set"); | |
58 assert(_cmst == NULL, "CMS thread already created"); | |
59 _cmst = this; | |
60 assert(_collector == NULL, "Collector already set"); | |
61 _collector = collector; | |
62 | |
63 set_name("Concurrent Mark-Sweep GC Thread"); | |
64 | |
65 if (os::create_thread(this, os::cgc_thread)) { | |
66 // XXX: need to set this to low priority | |
67 // unless "agressive mode" set; priority | |
68 // should be just less than that of VMThread. | |
69 os::set_priority(this, NearMaxPriority); | |
70 if (!DisableStartThread) { | |
71 os::start_thread(this); | |
72 } | |
73 } | |
74 _sltMonitor = SLT_lock; | |
75 set_icms_enabled(CMSIncrementalMode); | |
76 } | |
77 | |
78 void ConcurrentMarkSweepThread::run() { | |
79 assert(this == cmst(), "just checking"); | |
80 | |
81 this->record_stack_base_and_size(); | |
82 this->initialize_thread_local_storage(); | |
83 this->set_active_handles(JNIHandleBlock::allocate_block()); | |
84 // From this time Thread::current() should be working. | |
85 assert(this == Thread::current(), "just checking"); | |
86 if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) { | |
87 warning("Couldn't bind CMS thread to processor %u", CPUForCMSThread); | |
88 } | |
89 // Wait until Universe::is_fully_initialized() | |
90 { | |
91 CMSLoopCountWarn loopX("CMS::run", "waiting for " | |
92 "Universe::is_fully_initialized()", 2); | |
93 MutexLockerEx x(CGC_lock, true); | |
94 set_CMS_flag(CMS_cms_wants_token); | |
95 // Wait until Universe is initialized and all initialization is completed. | |
96 while (!is_init_completed() && !Universe::is_fully_initialized() && | |
97 !_should_terminate) { | |
98 CGC_lock->wait(true, 200); | |
99 loopX.tick(); | |
100 } | |
101 // Wait until the surrogate locker thread that will do | |
102 // pending list locking on our behalf has been created. | |
103 // We cannot start the SLT thread ourselves since we need | |
104 // to be a JavaThread to do so. | |
105 CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); | |
106 while (_slt == NULL && !_should_terminate) { | |
107 CGC_lock->wait(true, 200); | |
108 loopY.tick(); | |
109 } | |
110 clear_CMS_flag(CMS_cms_wants_token); | |
111 } | |
112 | |
113 while (!_should_terminate) { | |
114 sleepBeforeNextCycle(); | |
115 if (_should_terminate) break; | |
116 _collector->collect_in_background(false); // !clear_all_soft_refs | |
117 } | |
118 assert(_should_terminate, "just checking"); | |
119 // Check that the state of any protocol for synchronization | |
120 // between background (CMS) and foreground collector is "clean" | |
121 // (i.e. will not potentially block the foreground collector, | |
122 // requiring action by us). | |
123 verify_ok_to_terminate(); | |
124 // Signal that it is terminated | |
125 { | |
126 MutexLockerEx mu(Terminator_lock, | |
127 Mutex::_no_safepoint_check_flag); | |
128 assert(_cmst == this, "Weird!"); | |
129 _cmst = NULL; | |
130 Terminator_lock->notify(); | |
131 } | |
132 | |
133 // Thread destructor usually does this.. | |
134 ThreadLocalStorage::set_thread(NULL); | |
135 } | |
136 | |
137 #ifndef PRODUCT | |
138 void ConcurrentMarkSweepThread::verify_ok_to_terminate() const { | |
139 assert(!(CGC_lock->owned_by_self() || cms_thread_has_cms_token() || | |
140 cms_thread_wants_cms_token()), | |
141 "Must renounce all worldly possessions and desires for nirvana"); | |
142 _collector->verify_ok_to_terminate(); | |
143 } | |
144 #endif | |
145 | |
146 // create and start a new ConcurrentMarkSweep Thread for given CMS generation | |
147 ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) { | |
148 if (!_should_terminate) { | |
149 assert(cmst() == NULL, "start() called twice?"); | |
150 ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); | |
151 assert(cmst() == th, "Where did the just-created CMS thread go?"); | |
152 return th; | |
153 } | |
154 return NULL; | |
155 } | |
156 | |
157 void ConcurrentMarkSweepThread::stop() { | |
158 if (CMSIncrementalMode) { | |
159 // Disable incremental mode and wake up the thread so it notices the change. | |
160 disable_icms(); | |
161 start_icms(); | |
162 } | |
163 // it is ok to take late safepoints here, if needed | |
164 { | |
165 MutexLockerEx x(Terminator_lock); | |
166 _should_terminate = true; | |
167 } | |
168 { // Now post a notify on CGC_lock so as to nudge | |
169 // CMS thread(s) that might be slumbering in | |
170 // sleepBeforeNextCycle. | |
171 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); | |
172 CGC_lock->notify_all(); | |
173 } | |
174 { // Now wait until (all) CMS thread(s) have exited | |
175 MutexLockerEx x(Terminator_lock); | |
176 while(cmst() != NULL) { | |
177 Terminator_lock->wait(); | |
178 } | |
179 } | |
180 } | |
181 | |
182 void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) { | |
183 assert(tc != NULL, "Null ThreadClosure"); | |
184 if (_cmst != NULL) { | |
185 tc->do_thread(_cmst); | |
186 } | |
187 assert(Universe::is_fully_initialized(), | |
188 "Called too early, make sure heap is fully initialized"); | |
189 if (_collector != NULL) { | |
190 AbstractWorkGang* gang = _collector->conc_workers(); | |
191 if (gang != NULL) { | |
192 gang->threads_do(tc); | |
193 } | |
194 } | |
195 } | |
196 | |
197 void ConcurrentMarkSweepThread::print_on(outputStream* st) const { | |
198 st->print("\"%s\" ", name()); | |
199 Thread::print_on(st); | |
200 st->cr(); | |
201 } | |
202 | |
203 void ConcurrentMarkSweepThread::print_all_on(outputStream* st) { | |
204 if (_cmst != NULL) { | |
205 _cmst->print_on(st); | |
206 } | |
207 if (_collector != NULL) { | |
208 AbstractWorkGang* gang = _collector->conc_workers(); | |
209 if (gang != NULL) { | |
210 gang->print_worker_threads_on(st); | |
211 } | |
212 } | |
213 } | |
214 | |
215 void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) { | |
216 assert(UseConcMarkSweepGC, "just checking"); | |
217 | |
218 MutexLockerEx x(CGC_lock, | |
219 Mutex::_no_safepoint_check_flag); | |
220 if (!is_cms_thread) { | |
221 assert(Thread::current()->is_VM_thread(), "Not a VM thread"); | |
222 CMSSynchronousYieldRequest yr; | |
223 while (CMS_flag_is_set(CMS_cms_has_token)) { | |
224 // indicate that we want to get the token | |
225 set_CMS_flag(CMS_vm_wants_token); | |
226 CGC_lock->wait(true); | |
227 } | |
228 // claim the token and proceed | |
229 clear_CMS_flag(CMS_vm_wants_token); | |
230 set_CMS_flag(CMS_vm_has_token); | |
231 } else { | |
232 assert(Thread::current()->is_ConcurrentGC_thread(), | |
233 "Not a CMS thread"); | |
234 // The following barrier assumes there's only one CMS thread. | |
235 // This will need to be modified is there are more CMS threads than one. | |
236 while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) { | |
237 set_CMS_flag(CMS_cms_wants_token); | |
238 CGC_lock->wait(true); | |
239 } | |
240 // claim the token | |
241 clear_CMS_flag(CMS_cms_wants_token); | |
242 set_CMS_flag(CMS_cms_has_token); | |
243 } | |
244 } | |
245 | |
246 void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) { | |
247 assert(UseConcMarkSweepGC, "just checking"); | |
248 | |
249 MutexLockerEx x(CGC_lock, | |
250 Mutex::_no_safepoint_check_flag); | |
251 if (!is_cms_thread) { | |
252 assert(Thread::current()->is_VM_thread(), "Not a VM thread"); | |
253 assert(CMS_flag_is_set(CMS_vm_has_token), "just checking"); | |
254 clear_CMS_flag(CMS_vm_has_token); | |
255 if (CMS_flag_is_set(CMS_cms_wants_token)) { | |
256 // wake-up a waiting CMS thread | |
257 CGC_lock->notify(); | |
258 } | |
259 assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token), | |
260 "Should have been cleared"); | |
261 } else { | |
262 assert(Thread::current()->is_ConcurrentGC_thread(), | |
263 "Not a CMS thread"); | |
264 assert(CMS_flag_is_set(CMS_cms_has_token), "just checking"); | |
265 clear_CMS_flag(CMS_cms_has_token); | |
266 if (CMS_flag_is_set(CMS_vm_wants_token)) { | |
267 // wake-up a waiting VM thread | |
268 CGC_lock->notify(); | |
269 } | |
270 assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), | |
271 "Should have been cleared"); | |
272 } | |
273 } | |
274 | |
275 // Wait until the next synchronous GC or a timeout, whichever is earlier. | |
276 void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) { | |
277 MutexLockerEx x(CGC_lock, | |
278 Mutex::_no_safepoint_check_flag); | |
279 set_CMS_flag(CMS_cms_wants_token); // to provoke notifies | |
280 CGC_lock->wait(Mutex::_no_safepoint_check_flag, t); | |
281 clear_CMS_flag(CMS_cms_wants_token); | |
282 assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), | |
283 "Should not be set"); | |
284 } | |
285 | |
286 void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { | |
287 while (!_should_terminate) { | |
288 if (CMSIncrementalMode) { | |
289 icms_wait(); | |
290 return; | |
291 } else { | |
292 // Wait until the next synchronous GC or a timeout, whichever is earlier | |
293 wait_on_cms_lock(CMSWaitDuration); | |
294 } | |
295 // Check if we should start a CMS collection cycle | |
296 if (_collector->shouldConcurrentCollect()) { | |
297 return; | |
298 } | |
299 // .. collection criterion not yet met, let's go back | |
300 // and wait some more | |
301 } | |
302 } | |
303 | |
304 // Incremental CMS | |
305 void ConcurrentMarkSweepThread::start_icms() { | |
306 assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); | |
307 MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); | |
308 trace_state("start_icms"); | |
309 _should_run = true; | |
310 iCMS_lock->notify_all(); | |
311 } | |
312 | |
313 void ConcurrentMarkSweepThread::stop_icms() { | |
314 assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); | |
315 MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); | |
316 if (!_should_stop) { | |
317 trace_state("stop_icms"); | |
318 _should_stop = true; | |
319 _should_run = false; | |
320 asynchronous_yield_request(); | |
321 iCMS_lock->notify_all(); | |
322 } | |
323 } | |
324 | |
325 void ConcurrentMarkSweepThread::icms_wait() { | |
326 assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); | |
327 if (_should_stop && icms_enabled()) { | |
328 MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); | |
329 trace_state("pause_icms"); | |
330 _collector->stats().stop_cms_timer(); | |
331 while(!_should_run && icms_enabled()) { | |
332 iCMS_lock->wait(Mutex::_no_safepoint_check_flag); | |
333 } | |
334 _collector->stats().start_cms_timer(); | |
335 _should_stop = false; | |
336 trace_state("pause_icms end"); | |
337 } | |
338 } | |
339 | |
340 // Note: this method, although exported by the ConcurrentMarkSweepThread, | |
341 // which is a non-JavaThread, can only be called by a JavaThread. | |
342 // Currently this is done at vm creation time (post-vm-init) by the | |
343 // main/Primordial (Java)Thread. | |
344 // XXX Consider changing this in the future to allow the CMS thread | |
345 // itself to create this thread? | |
346 void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) { | |
347 assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC"); | |
348 assert(_slt == NULL, "SLT already created"); | |
349 _slt = SurrogateLockerThread::make(THREAD); | |
350 } |