Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp @ 1648:8099e71601df
6968368: SIGSEGV in the BCEscapeAnalyzer::copy_dependencies
Summary: Use GrowableArray and VectorSet allocated in ciEnv arena.
Reviewed-by: never, twisti
author | kvn |
---|---|
date | Wed, 14 Jul 2010 14:47:34 -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 } |