Wed, 19 Jan 2011 19:30:42 -0500
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
1 /*
2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
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"
34 // ======= Concurrent Mark Thread ========
36 // The CM thread is created when the G1 garbage collector is used
38 SurrogateLockerThread*
39 ConcurrentMarkThread::_slt = NULL;
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 }
53 class CMCheckpointRootsInitialClosure: public VoidClosure {
55 ConcurrentMark* _cm;
56 public:
58 CMCheckpointRootsInitialClosure(ConcurrentMark* cm) :
59 _cm(cm) {}
61 void do_void(){
62 _cm->checkpointRootsInitial();
63 }
64 };
66 class CMCheckpointRootsFinalClosure: public VoidClosure {
68 ConcurrentMark* _cm;
69 public:
71 CMCheckpointRootsFinalClosure(ConcurrentMark* cm) :
72 _cm(cm) {}
74 void do_void(){
75 _cm->checkpointRootsFinal(false); // !clear_all_soft_refs
76 }
77 };
79 class CMCleanUp: public VoidClosure {
80 ConcurrentMark* _cm;
81 public:
83 CMCleanUp(ConcurrentMark* cm) :
84 _cm(cm) {}
86 void do_void(){
87 _cm->cleanup();
88 }
89 };
93 void ConcurrentMarkThread::run() {
94 initialize_in_thread();
95 _vtime_start = os::elapsedVTime();
96 wait_for_universe_init();
98 G1CollectedHeap* g1h = G1CollectedHeap::heap();
99 G1CollectorPolicy* g1_policy = g1h->g1_policy();
100 G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
101 Thread *current_thread = Thread::current();
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];
113 if (PrintGC) {
114 gclog_or_tty->date_stamp(PrintGCDateStamps);
115 gclog_or_tty->stamp(PrintGCTimeStamps);
116 gclog_or_tty->print_cr("[GC concurrent-mark-start]");
117 }
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
122 g1h->set_marking_complete();
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 }
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 }
140 int iter = 0;
141 do {
142 iter++;
143 if (!cm()->has_aborted()) {
144 _cm->markFromRoots();
145 }
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 }
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 }
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 }
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();
186 // YSR: These look dubious (i.e. redundant) !!! FIX ME
187 slt()->manipulatePLL(SurrogateLockerThread::acquirePLL);
188 slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
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 }
198 _sts.join();
199 _cm->calcDesiredRegions();
200 _sts.leave();
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 }
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 {
231 g1h->set_marking_complete();
232 }
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.
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 }
252 // Now do the remainder of the cleanup operation.
253 _cm->completeCleanup();
254 g1_policy->record_concurrent_mark_cleanup_completed();
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);
262 }
264 // We're done: no more free regions coming.
265 g1h->reset_free_regions_coming();
266 }
267 guarantee(cm()->cleanup_list_is_empty(),
268 "at this point there should be no regions on the cleanup list");
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 }
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 }
285 // Update the number of full collections that have been
286 // completed. This will also notify the FullGCCount_lock in case a
287 // Java thread is waiting for a full GC to happen (e.g., it
288 // called System.gc() with +ExplicitGCInvokesConcurrent).
289 _sts.join();
290 g1h->increment_full_collections_completed(true /* concurrent */);
291 _sts.leave();
292 }
293 assert(_should_terminate, "just checking");
295 terminate();
296 }
299 void ConcurrentMarkThread::yield() {
300 _sts.yield("Concurrent Mark");
301 }
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 }
312 void ConcurrentMarkThread::print() const {
313 print_on(tty);
314 }
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();
320 }
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.
325 assert(!in_progress(), "should have been cleared");
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 }
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 }