src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp

Wed, 19 Jan 2011 19:30:42 -0500

author
tonyp
date
Wed, 19 Jan 2011 19:30:42 -0500
changeset 2472
0fa27f37d4d4
parent 2372
fb712ff22571
child 2492
a672e43650cc
permissions
-rw-r--r--

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 }

mercurial