Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @ 2152:0fa27f37d4d4
6977804: G1: remove the zero-filling thread
Summary: This changeset removes the zero-filling thread from G1 and collapses the two free region lists we had before (the "free" and "unclean" lists) into one. The new free list uses the new heap region sets / lists abstractions that we'll ultimately use it to keep track of all regions in the heap. A heap region set was also introduced for the humongous regions. Finally, this change increases the concurrency between the thread that completes freeing regions (after a cleanup pause) and the rest of the system (before we'd have to wait for said thread to complete before allocating a new region). The changest also includes a lot of refactoring and code simplification.
Reviewed-by: jcoomes, johnc
author | tonyp |
---|---|
date | Wed, 19 Jan 2011 19:30:42 -0500 |
parents | fb712ff22571 |
children | a672e43650cc |
rev | line source |
---|---|
342 | 1 /* |
2152 | 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. |
342 | 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:
1019
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1019
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:
1019
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" | |
27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | |
28 #include "gc_implementation/g1/g1CollectorPolicy.hpp" | |
29 #include "gc_implementation/g1/g1MMUTracker.hpp" | |
30 #include "gc_implementation/g1/vm_operations_g1.hpp" | |
31 #include "memory/resourceArea.hpp" | |
32 #include "runtime/vmThread.hpp" | |
342 | 33 |
34 // ======= Concurrent Mark Thread ======== | |
35 | |
36 // The CM thread is created when the G1 garbage collector is used | |
37 | |
38 SurrogateLockerThread* | |
39 ConcurrentMarkThread::_slt = NULL; | |
40 | |
41 ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : | |
42 ConcurrentGCThread(), | |
43 _cm(cm), | |
44 _started(false), | |
45 _in_progress(false), | |
46 _vtime_accum(0.0), | |
47 _vtime_mark_accum(0.0), | |
48 _vtime_count_accum(0.0) | |
49 { | |
50 create_and_start(); | |
51 } | |
52 | |
53 class CMCheckpointRootsInitialClosure: public VoidClosure { | |
54 | |
55 ConcurrentMark* _cm; | |
56 public: | |
57 | |
58 CMCheckpointRootsInitialClosure(ConcurrentMark* cm) : | |
59 _cm(cm) {} | |
60 | |
61 void do_void(){ | |
62 _cm->checkpointRootsInitial(); | |
63 } | |
64 }; | |
65 | |
66 class CMCheckpointRootsFinalClosure: public VoidClosure { | |
67 | |
68 ConcurrentMark* _cm; | |
69 public: | |
70 | |
71 CMCheckpointRootsFinalClosure(ConcurrentMark* cm) : | |
72 _cm(cm) {} | |
73 | |
74 void do_void(){ | |
75 _cm->checkpointRootsFinal(false); // !clear_all_soft_refs | |
76 } | |
77 }; | |
78 | |
79 class CMCleanUp: public VoidClosure { | |
80 ConcurrentMark* _cm; | |
81 public: | |
82 | |
83 CMCleanUp(ConcurrentMark* cm) : | |
84 _cm(cm) {} | |
85 | |
86 void do_void(){ | |
87 _cm->cleanup(); | |
88 } | |
89 }; | |
90 | |
91 | |
92 | |
93 void ConcurrentMarkThread::run() { | |
94 initialize_in_thread(); | |
95 _vtime_start = os::elapsedVTime(); | |
96 wait_for_universe_init(); | |
97 | |
2152 | 98 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
99 G1CollectorPolicy* g1_policy = g1h->g1_policy(); | |
342 | 100 G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); |
101 Thread *current_thread = Thread::current(); | |
102 | |
103 while (!_should_terminate) { | |
104 // wait until started is set. | |
105 sleepBeforeNextCycle(); | |
106 { | |
107 ResourceMark rm; | |
108 HandleMark hm; | |
109 double cycle_start = os::elapsedVTime(); | |
110 double mark_start_sec = os::elapsedTime(); | |
111 char verbose_str[128]; | |
112 | |
113 if (PrintGC) { | |
114 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
115 gclog_or_tty->stamp(PrintGCTimeStamps); | |
619
7ea5ca260b28
6814467: G1: small fixes related to concurrent marking verboseness
tonyp
parents:
342
diff
changeset
|
116 gclog_or_tty->print_cr("[GC concurrent-mark-start]"); |
342 | 117 } |
118 | |
119 if (!g1_policy->in_young_gc_mode()) { | |
120 // this ensures the flag is not set if we bail out of the marking | |
121 // cycle; normally the flag is cleared immediately after cleanup | |
2152 | 122 g1h->set_marking_complete(); |
342 | 123 |
124 if (g1_policy->adaptive_young_list_length()) { | |
125 double now = os::elapsedTime(); | |
126 double init_prediction_ms = g1_policy->predict_init_time_ms(); | |
127 jlong sleep_time_ms = mmu_tracker->when_ms(now, init_prediction_ms); | |
128 os::sleep(current_thread, sleep_time_ms, false); | |
129 } | |
130 | |
131 // We don't have to skip here if we've been asked to restart, because | |
132 // in the worst case we just enqueue a new VM operation to start a | |
133 // marking. Note that the init operation resets has_aborted() | |
134 CMCheckpointRootsInitialClosure init_cl(_cm); | |
135 strcpy(verbose_str, "GC initial-mark"); | |
136 VM_CGC_Operation op(&init_cl, verbose_str); | |
137 VMThread::execute(&op); | |
138 } | |
139 | |
140 int iter = 0; | |
141 do { | |
142 iter++; | |
143 if (!cm()->has_aborted()) { | |
144 _cm->markFromRoots(); | |
145 } | |
146 | |
147 double mark_end_time = os::elapsedVTime(); | |
148 double mark_end_sec = os::elapsedTime(); | |
149 _vtime_mark_accum += (mark_end_time - cycle_start); | |
150 if (!cm()->has_aborted()) { | |
151 if (g1_policy->adaptive_young_list_length()) { | |
152 double now = os::elapsedTime(); | |
153 double remark_prediction_ms = g1_policy->predict_remark_time_ms(); | |
154 jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms); | |
155 os::sleep(current_thread, sleep_time_ms, false); | |
156 } | |
157 | |
158 if (PrintGC) { | |
159 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
160 gclog_or_tty->stamp(PrintGCTimeStamps); | |
161 gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]", | |
162 mark_end_sec - mark_start_sec); | |
163 } | |
164 | |
165 CMCheckpointRootsFinalClosure final_cl(_cm); | |
166 sprintf(verbose_str, "GC remark"); | |
167 VM_CGC_Operation op(&final_cl, verbose_str); | |
168 VMThread::execute(&op); | |
169 } | |
170 if (cm()->restart_for_overflow() && | |
171 G1TraceMarkStackOverflow) { | |
172 gclog_or_tty->print_cr("Restarting conc marking because of MS overflow " | |
173 "in remark (restart #%d).", iter); | |
174 } | |
175 | |
176 if (cm()->restart_for_overflow()) { | |
177 if (PrintGC) { | |
178 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
179 gclog_or_tty->stamp(PrintGCTimeStamps); | |
180 gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]"); | |
181 } | |
182 } | |
183 } while (cm()->restart_for_overflow()); | |
184 double counting_start_time = os::elapsedVTime(); | |
185 | |
186 // YSR: These look dubious (i.e. redundant) !!! FIX ME | |
187 slt()->manipulatePLL(SurrogateLockerThread::acquirePLL); | |
188 slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL); | |
189 | |
190 if (!cm()->has_aborted()) { | |
191 double count_start_sec = os::elapsedTime(); | |
192 if (PrintGC) { | |
193 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
194 gclog_or_tty->stamp(PrintGCTimeStamps); | |
195 gclog_or_tty->print_cr("[GC concurrent-count-start]"); | |
196 } | |
197 | |
198 _sts.join(); | |
199 _cm->calcDesiredRegions(); | |
200 _sts.leave(); | |
201 | |
202 if (!cm()->has_aborted()) { | |
203 double count_end_sec = os::elapsedTime(); | |
204 if (PrintGC) { | |
205 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
206 gclog_or_tty->stamp(PrintGCTimeStamps); | |
207 gclog_or_tty->print_cr("[GC concurrent-count-end, %1.7lf]", | |
208 count_end_sec - count_start_sec); | |
209 } | |
210 } | |
211 } | |
212 double end_time = os::elapsedVTime(); | |
213 _vtime_count_accum += (end_time - counting_start_time); | |
214 // Update the total virtual time before doing this, since it will try | |
215 // to measure it to get the vtime for this marking. We purposely | |
216 // neglect the presumably-short "completeCleanup" phase here. | |
217 _vtime_accum = (end_time - _vtime_start); | |
218 if (!cm()->has_aborted()) { | |
219 if (g1_policy->adaptive_young_list_length()) { | |
220 double now = os::elapsedTime(); | |
221 double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms(); | |
222 jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms); | |
223 os::sleep(current_thread, sleep_time_ms, false); | |
224 } | |
225 | |
226 CMCleanUp cl_cl(_cm); | |
227 sprintf(verbose_str, "GC cleanup"); | |
228 VM_CGC_Operation op(&cl_cl, verbose_str); | |
229 VMThread::execute(&op); | |
230 } else { | |
2152 | 231 g1h->set_marking_complete(); |
342 | 232 } |
233 | |
2152 | 234 // Check if cleanup set the free_regions_coming flag. If it |
235 // hasn't, we can just skip the next step. | |
236 if (g1h->free_regions_coming()) { | |
237 // The following will finish freeing up any regions that we | |
238 // found to be empty during cleanup. We'll do this part | |
239 // without joining the suspendible set. If an evacuation pause | |
240 // takes places, then we would carry on freeing regions in | |
241 // case they are needed by the pause. If a Full GC takes | |
242 // places, it would wait for us to process the regions | |
243 // reclaimed by cleanup. | |
244 | |
342 | 245 double cleanup_start_sec = os::elapsedTime(); |
246 if (PrintGC) { | |
247 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
248 gclog_or_tty->stamp(PrintGCTimeStamps); | |
249 gclog_or_tty->print_cr("[GC concurrent-cleanup-start]"); | |
250 } | |
251 | |
252 // Now do the remainder of the cleanup operation. | |
253 _cm->completeCleanup(); | |
2152 | 254 g1_policy->record_concurrent_mark_cleanup_completed(); |
342 | 255 |
2152 | 256 double cleanup_end_sec = os::elapsedTime(); |
257 if (PrintGC) { | |
258 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
259 gclog_or_tty->stamp(PrintGCTimeStamps); | |
260 gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]", | |
261 cleanup_end_sec - cleanup_start_sec); | |
342 | 262 } |
2152 | 263 |
264 // We're done: no more free regions coming. | |
265 g1h->reset_free_regions_coming(); | |
342 | 266 } |
2152 | 267 guarantee(cm()->cleanup_list_is_empty(), |
268 "at this point there should be no regions on the cleanup list"); | |
342 | 269 |
270 if (cm()->has_aborted()) { | |
271 if (PrintGC) { | |
272 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
273 gclog_or_tty->stamp(PrintGCTimeStamps); | |
274 gclog_or_tty->print_cr("[GC concurrent-mark-abort]"); | |
275 } | |
276 } | |
277 | |
278 // we now want to allow clearing of the marking bitmap to be | |
279 // suspended by a collection pause. | |
280 _sts.join(); | |
281 _cm->clearNextBitmap(); | |
282 _sts.leave(); | |
283 } | |
1656
4e5661ba9d98
6944166: G1: explicit GCs are not always handled correctly
tonyp
parents:
1552
diff
changeset
|
284 |
4e5661ba9d98
6944166: G1: explicit GCs are not always handled correctly
tonyp
parents:
1552
diff
changeset
|
285 // Update the number of full collections that have been |
4e5661ba9d98
6944166: G1: explicit GCs are not always handled correctly
tonyp
parents:
1552
diff
changeset
|
286 // completed. This will also notify the FullGCCount_lock in case a |
4e5661ba9d98
6944166: G1: explicit GCs are not always handled correctly
tonyp
parents:
1552
diff
changeset
|
287 // Java thread is waiting for a full GC to happen (e.g., it |
4e5661ba9d98
6944166: G1: explicit GCs are not always handled correctly
tonyp
parents:
1552
diff
changeset
|
288 // called System.gc() with +ExplicitGCInvokesConcurrent). |
2030
fb712ff22571
7000559: G1: assertion failure !outer || (full_collections_started == _full_collections_completed + 1)
tonyp
parents:
1972
diff
changeset
|
289 _sts.join(); |
2152 | 290 g1h->increment_full_collections_completed(true /* concurrent */); |
2030
fb712ff22571
7000559: G1: assertion failure !outer || (full_collections_started == _full_collections_completed + 1)
tonyp
parents:
1972
diff
changeset
|
291 _sts.leave(); |
342 | 292 } |
293 assert(_should_terminate, "just checking"); | |
294 | |
295 terminate(); | |
296 } | |
297 | |
298 | |
299 void ConcurrentMarkThread::yield() { | |
300 _sts.yield("Concurrent Mark"); | |
301 } | |
302 | |
303 void ConcurrentMarkThread::stop() { | |
304 // it is ok to take late safepoints here, if needed | |
305 MutexLockerEx mu(Terminator_lock); | |
306 _should_terminate = true; | |
307 while (!_has_terminated) { | |
308 Terminator_lock->wait(); | |
309 } | |
310 } | |
311 | |
1019 | 312 void ConcurrentMarkThread::print() const { |
313 print_on(tty); | |
314 } | |
315 | |
316 void ConcurrentMarkThread::print_on(outputStream* st) const { | |
317 st->print("\"G1 Main Concurrent Mark GC Thread\" "); | |
318 Thread::print_on(st); | |
319 st->cr(); | |
342 | 320 } |
321 | |
322 void ConcurrentMarkThread::sleepBeforeNextCycle() { | |
323 // We join here because we don't want to do the "shouldConcurrentMark()" | |
324 // below while the world is otherwise stopped. | |
1840
4e0094bc41fa
6983311: G1: LoopTest hangs when run with -XX:+ExplicitInvokesConcurrent
johnc
parents:
1656
diff
changeset
|
325 assert(!in_progress(), "should have been cleared"); |
4e0094bc41fa
6983311: G1: LoopTest hangs when run with -XX:+ExplicitInvokesConcurrent
johnc
parents:
1656
diff
changeset
|
326 |
342 | 327 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); |
328 while (!started()) { | |
329 CGC_lock->wait(Mutex::_no_safepoint_check_flag); | |
330 } | |
331 set_in_progress(); | |
332 clear_started(); | |
333 } | |
334 | |
335 // Note: this method, although exported by the ConcurrentMarkSweepThread, | |
336 // which is a non-JavaThread, can only be called by a JavaThread. | |
337 // Currently this is done at vm creation time (post-vm-init) by the | |
338 // main/Primordial (Java)Thread. | |
339 // XXX Consider changing this in the future to allow the CMS thread | |
340 // itself to create this thread? | |
341 void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) { | |
342 assert(_slt == NULL, "SLT already created"); | |
343 _slt = SurrogateLockerThread::make(THREAD); | |
344 } |