src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 2314
f95d63e2154a
child 3294
bca17e38de00
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

duke@435 1
duke@435 2 /*
stefank@2314 3 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 5 *
duke@435 6 * This code is free software; you can redistribute it and/or modify it
duke@435 7 * under the terms of the GNU General Public License version 2 only, as
duke@435 8 * published by the Free Software Foundation.
duke@435 9 *
duke@435 10 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 13 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 14 * accompanied this code).
duke@435 15 *
duke@435 16 * You should have received a copy of the GNU General Public License version
duke@435 17 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 19 *
trims@1907 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 21 * or visit www.oracle.com if you need additional information or have any
trims@1907 22 * questions.
duke@435 23 *
duke@435 24 */
duke@435 25
stefank@2314 26 #include "precompiled.hpp"
stefank@2314 27 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
stefank@2314 28 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp"
stefank@2314 29 #include "memory/allocation.hpp"
stefank@2314 30 #include "memory/allocation.inline.hpp"
stefank@2314 31 #include "memory/resourceArea.hpp"
stefank@2314 32 #include "runtime/handles.hpp"
stefank@2314 33 #include "runtime/handles.inline.hpp"
stefank@2314 34 #include "runtime/os.hpp"
stefank@2314 35 #include "runtime/thread.hpp"
duke@435 36
duke@435 37 GCTaskThread::GCTaskThread(GCTaskManager* manager,
duke@435 38 uint which,
duke@435 39 uint processor_id) :
duke@435 40 _manager(manager),
duke@435 41 _processor_id(processor_id),
duke@435 42 _time_stamps(NULL),
duke@435 43 _time_stamp_index(0)
duke@435 44 {
duke@435 45 if (!os::create_thread(this, os::pgc_thread))
duke@435 46 vm_exit_out_of_memory(0, "Cannot create GC thread. Out of system resources.");
duke@435 47
duke@435 48 if (PrintGCTaskTimeStamps) {
duke@435 49 _time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries );
duke@435 50
duke@435 51 guarantee(_time_stamps != NULL, "Sanity");
duke@435 52 }
duke@435 53 set_id(which);
duke@435 54 set_name("GC task thread#%d (ParallelGC)", which);
duke@435 55 }
duke@435 56
duke@435 57 GCTaskThread::~GCTaskThread() {
duke@435 58 if (_time_stamps != NULL) {
duke@435 59 FREE_C_HEAP_ARRAY(GCTaskTimeStamp, _time_stamps);
duke@435 60 }
duke@435 61 }
duke@435 62
duke@435 63 void GCTaskThread::start() {
duke@435 64 os::start_thread(this);
duke@435 65 }
duke@435 66
duke@435 67 GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) {
duke@435 68 guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries");
duke@435 69
duke@435 70 return &(_time_stamps[index]);
duke@435 71 }
duke@435 72
duke@435 73 void GCTaskThread::print_task_time_stamps() {
duke@435 74 assert(PrintGCTaskTimeStamps, "Sanity");
duke@435 75 assert(_time_stamps != NULL, "Sanity (Probably set PrintGCTaskTimeStamps late)");
duke@435 76
duke@435 77 tty->print_cr("GC-Thread %u entries: %d", id(), _time_stamp_index);
duke@435 78 for(uint i=0; i<_time_stamp_index; i++) {
duke@435 79 GCTaskTimeStamp* time_stamp = time_stamp_at(i);
duke@435 80 tty->print_cr("\t[ %s " INT64_FORMAT " " INT64_FORMAT " ]",
duke@435 81 time_stamp->name(),
duke@435 82 time_stamp->entry_time(),
duke@435 83 time_stamp->exit_time());
duke@435 84 }
duke@435 85
duke@435 86 // Reset after dumping the data
duke@435 87 _time_stamp_index = 0;
duke@435 88 }
duke@435 89
duke@435 90 void GCTaskThread::print_on(outputStream* st) const {
duke@435 91 st->print("\"%s\" ", name());
duke@435 92 Thread::print_on(st);
duke@435 93 st->cr();
duke@435 94 }
duke@435 95
duke@435 96 void GCTaskThread::run() {
duke@435 97 // Set up the thread for stack overflow support
duke@435 98 this->record_stack_base_and_size();
duke@435 99 this->initialize_thread_local_storage();
duke@435 100 // Bind yourself to your processor.
duke@435 101 if (processor_id() != GCTaskManager::sentinel_worker()) {
duke@435 102 if (TraceGCTaskThread) {
duke@435 103 tty->print_cr("GCTaskThread::run: "
duke@435 104 " binding to processor %u", processor_id());
duke@435 105 }
duke@435 106 if (!os::bind_to_processor(processor_id())) {
duke@435 107 DEBUG_ONLY(
duke@435 108 warning("Couldn't bind GCTaskThread %u to processor %u",
duke@435 109 which(), processor_id());
duke@435 110 )
duke@435 111 }
duke@435 112 }
duke@435 113 // Part of thread setup.
duke@435 114 // ??? Are these set up once here to make subsequent ones fast?
duke@435 115 HandleMark hm_outer;
duke@435 116 ResourceMark rm_outer;
duke@435 117
duke@435 118 TimeStamp timer;
duke@435 119
duke@435 120 for (;/* ever */;) {
duke@435 121 // These are so we can flush the resources allocated in the inner loop.
duke@435 122 HandleMark hm_inner;
duke@435 123 ResourceMark rm_inner;
duke@435 124 for (; /* break */; ) {
duke@435 125 // This will block until there is a task to be gotten.
duke@435 126 GCTask* task = manager()->get_task(which());
duke@435 127
duke@435 128 // In case the update is costly
duke@435 129 if (PrintGCTaskTimeStamps) {
duke@435 130 timer.update();
duke@435 131 }
duke@435 132
duke@435 133 jlong entry_time = timer.ticks();
duke@435 134 char* name = task->name();
duke@435 135
duke@435 136 task->do_it(manager(), which());
duke@435 137 manager()->note_completion(which());
duke@435 138
duke@435 139 if (PrintGCTaskTimeStamps) {
duke@435 140 assert(_time_stamps != NULL, "Sanity (PrintGCTaskTimeStamps set late?)");
duke@435 141
duke@435 142 timer.update();
duke@435 143
duke@435 144 GCTaskTimeStamp* time_stamp = time_stamp_at(_time_stamp_index++);
duke@435 145
duke@435 146 time_stamp->set_name(name);
duke@435 147 time_stamp->set_entry_time(entry_time);
duke@435 148 time_stamp->set_exit_time(timer.ticks());
duke@435 149 }
duke@435 150
duke@435 151 // Check if we should release our inner resources.
duke@435 152 if (manager()->should_release_resources(which())) {
duke@435 153 manager()->note_release(which());
duke@435 154 break;
duke@435 155 }
duke@435 156 }
duke@435 157 }
duke@435 158 }

mercurial