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