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