Thu, 20 Nov 2008 16:56:09 -0800
6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
1 /*
2 * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved.
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 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
25 # include "incls/_precompiled.incl"
26 # include "incls/_concurrentMarkSweepThread.cpp.incl"
28 // ======= Concurrent Mark Sweep Thread ========
30 // The CMS thread is created when Concurrent Mark Sweep is used in the
31 // older of two generations in a generational memory system.
33 ConcurrentMarkSweepThread*
34 ConcurrentMarkSweepThread::_cmst = NULL;
35 CMSCollector* ConcurrentMarkSweepThread::_collector = NULL;
36 bool ConcurrentMarkSweepThread::_should_terminate = false;
37 int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;
39 volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;
40 volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0;
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;
48 SurrogateLockerThread*
49 ConcurrentMarkSweepThread::_slt = NULL;
50 SurrogateLockerThread::SLT_msg_type
51 ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;
52 Monitor*
53 ConcurrentMarkSweepThread::_sltMonitor = NULL;
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;
63 set_name("Concurrent Mark-Sweep GC Thread");
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 }
78 void ConcurrentMarkSweepThread::run() {
79 assert(this == cmst(), "just checking");
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 }
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 }
133 // Thread destructor usually does this..
134 ThreadLocalStorage::set_thread(NULL);
135 }
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
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 }
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 }
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 }
197 void ConcurrentMarkSweepThread::print_on(outputStream* st) const {
198 st->print("\"%s\" ", name());
199 Thread::print_on(st);
200 st->cr();
201 }
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 }
215 void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) {
216 assert(UseConcMarkSweepGC, "just checking");
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 }
246 void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {
247 assert(UseConcMarkSweepGC, "just checking");
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 }
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 }
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 }
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 }
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 }
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 }
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 }