duke@435: duke@435: /* trims@1907: * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: duke@435: #include "incls/_precompiled.incl" duke@435: #include "incls/_gcTaskThread.cpp.incl" duke@435: duke@435: GCTaskThread::GCTaskThread(GCTaskManager* manager, duke@435: uint which, duke@435: uint processor_id) : duke@435: _manager(manager), duke@435: _processor_id(processor_id), duke@435: _time_stamps(NULL), duke@435: _time_stamp_index(0) duke@435: { duke@435: if (!os::create_thread(this, os::pgc_thread)) duke@435: vm_exit_out_of_memory(0, "Cannot create GC thread. Out of system resources."); duke@435: duke@435: if (PrintGCTaskTimeStamps) { duke@435: _time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries ); duke@435: duke@435: guarantee(_time_stamps != NULL, "Sanity"); duke@435: } duke@435: set_id(which); duke@435: set_name("GC task thread#%d (ParallelGC)", which); duke@435: } duke@435: duke@435: GCTaskThread::~GCTaskThread() { duke@435: if (_time_stamps != NULL) { duke@435: FREE_C_HEAP_ARRAY(GCTaskTimeStamp, _time_stamps); duke@435: } duke@435: } duke@435: duke@435: void GCTaskThread::start() { duke@435: os::start_thread(this); duke@435: } duke@435: duke@435: GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) { duke@435: guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries"); duke@435: duke@435: return &(_time_stamps[index]); duke@435: } duke@435: duke@435: void GCTaskThread::print_task_time_stamps() { duke@435: assert(PrintGCTaskTimeStamps, "Sanity"); duke@435: assert(_time_stamps != NULL, "Sanity (Probably set PrintGCTaskTimeStamps late)"); duke@435: duke@435: tty->print_cr("GC-Thread %u entries: %d", id(), _time_stamp_index); duke@435: for(uint i=0; i<_time_stamp_index; i++) { duke@435: GCTaskTimeStamp* time_stamp = time_stamp_at(i); duke@435: tty->print_cr("\t[ %s " INT64_FORMAT " " INT64_FORMAT " ]", duke@435: time_stamp->name(), duke@435: time_stamp->entry_time(), duke@435: time_stamp->exit_time()); duke@435: } duke@435: duke@435: // Reset after dumping the data duke@435: _time_stamp_index = 0; duke@435: } duke@435: duke@435: void GCTaskThread::print_on(outputStream* st) const { duke@435: st->print("\"%s\" ", name()); duke@435: Thread::print_on(st); duke@435: st->cr(); duke@435: } duke@435: duke@435: void GCTaskThread::run() { duke@435: // Set up the thread for stack overflow support duke@435: this->record_stack_base_and_size(); duke@435: this->initialize_thread_local_storage(); duke@435: // Bind yourself to your processor. duke@435: if (processor_id() != GCTaskManager::sentinel_worker()) { duke@435: if (TraceGCTaskThread) { duke@435: tty->print_cr("GCTaskThread::run: " duke@435: " binding to processor %u", processor_id()); duke@435: } duke@435: if (!os::bind_to_processor(processor_id())) { duke@435: DEBUG_ONLY( duke@435: warning("Couldn't bind GCTaskThread %u to processor %u", duke@435: which(), processor_id()); duke@435: ) duke@435: } duke@435: } duke@435: // Part of thread setup. duke@435: // ??? Are these set up once here to make subsequent ones fast? duke@435: HandleMark hm_outer; duke@435: ResourceMark rm_outer; duke@435: duke@435: TimeStamp timer; duke@435: duke@435: for (;/* ever */;) { duke@435: // These are so we can flush the resources allocated in the inner loop. duke@435: HandleMark hm_inner; duke@435: ResourceMark rm_inner; duke@435: for (; /* break */; ) { duke@435: // This will block until there is a task to be gotten. duke@435: GCTask* task = manager()->get_task(which()); duke@435: duke@435: // In case the update is costly duke@435: if (PrintGCTaskTimeStamps) { duke@435: timer.update(); duke@435: } duke@435: duke@435: jlong entry_time = timer.ticks(); duke@435: char* name = task->name(); duke@435: duke@435: task->do_it(manager(), which()); duke@435: manager()->note_completion(which()); duke@435: duke@435: if (PrintGCTaskTimeStamps) { duke@435: assert(_time_stamps != NULL, "Sanity (PrintGCTaskTimeStamps set late?)"); duke@435: duke@435: timer.update(); duke@435: duke@435: GCTaskTimeStamp* time_stamp = time_stamp_at(_time_stamp_index++); duke@435: duke@435: time_stamp->set_name(name); duke@435: time_stamp->set_entry_time(entry_time); duke@435: time_stamp->set_exit_time(timer.ticks()); duke@435: } duke@435: duke@435: // Check if we should release our inner resources. duke@435: if (manager()->should_release_resources(which())) { duke@435: manager()->note_release(which()); duke@435: break; duke@435: } duke@435: } duke@435: } duke@435: }