duke@435: /* duke@435: * Copyright 1997-2007 Sun Microsystems, Inc. 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: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: # include "incls/_precompiled.incl" duke@435: # include "incls/_task.cpp.incl" duke@435: duke@435: int PeriodicTask::_num_tasks = 0; duke@435: PeriodicTask* PeriodicTask::_tasks[PeriodicTask::max_tasks]; duke@435: #ifndef PRODUCT duke@435: elapsedTimer PeriodicTask::_timer; duke@435: int PeriodicTask::_intervalHistogram[PeriodicTask::max_interval]; duke@435: int PeriodicTask::_ticks; duke@435: duke@435: void PeriodicTask::print_intervals() { duke@435: if (ProfilerCheckIntervals) { duke@435: for (int i = 0; i < PeriodicTask::max_interval; i++) { duke@435: int n = _intervalHistogram[i]; duke@435: if (n > 0) tty->print_cr("%3d: %5d (%4.1f%%)", i, n, 100.0 * n / _ticks); duke@435: } duke@435: } duke@435: } duke@435: #endif duke@435: duke@435: void PeriodicTask::real_time_tick(size_t delay_time) { duke@435: #ifndef PRODUCT duke@435: if (ProfilerCheckIntervals) { duke@435: _ticks++; duke@435: _timer.stop(); duke@435: int ms = (int)(_timer.seconds() * 1000.0); duke@435: _timer.reset(); duke@435: _timer.start(); duke@435: if (ms >= PeriodicTask::max_interval) ms = PeriodicTask::max_interval - 1; duke@435: _intervalHistogram[ms]++; duke@435: } duke@435: #endif duke@435: int orig_num_tasks = _num_tasks; duke@435: for(int index = 0; index < _num_tasks; index++) { duke@435: _tasks[index]->execute_if_pending(delay_time); duke@435: if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself duke@435: index--; // re-do current slot as it has changed duke@435: orig_num_tasks = _num_tasks; duke@435: } duke@435: } duke@435: } duke@435: duke@435: duke@435: PeriodicTask::PeriodicTask(size_t interval_time) : duke@435: _counter(0), _interval(interval_time) { duke@435: assert(is_init_completed(), "Periodic tasks should not start during VM initialization"); duke@435: // Sanity check the interval time duke@435: assert(_interval >= PeriodicTask::min_interval && duke@435: _interval <= PeriodicTask::max_interval && duke@435: _interval % PeriodicTask::interval_gran == 0, duke@435: "improper PeriodicTask interval time"); duke@435: } duke@435: duke@435: PeriodicTask::~PeriodicTask() { duke@435: if (is_enrolled()) duke@435: disenroll(); duke@435: } duke@435: duke@435: bool PeriodicTask::is_enrolled() const { duke@435: for(int index = 0; index < _num_tasks; index++) duke@435: if (_tasks[index] == this) return true; duke@435: return false; duke@435: } duke@435: duke@435: void PeriodicTask::enroll() { duke@435: assert(WatcherThread::watcher_thread() == NULL, "dynamic enrollment of tasks not yet supported"); duke@435: duke@435: if (_num_tasks == PeriodicTask::max_tasks) duke@435: fatal("Overflow in PeriodicTask table"); duke@435: _tasks[_num_tasks++] = this; duke@435: } duke@435: duke@435: void PeriodicTask::disenroll() { duke@435: assert(WatcherThread::watcher_thread() == NULL || duke@435: Thread::current() == WatcherThread::watcher_thread(), duke@435: "dynamic disenrollment currently only handled from WatcherThread from within task() method"); duke@435: duke@435: int index; duke@435: for(index = 0; index < _num_tasks && _tasks[index] != this; index++); duke@435: if (index == _num_tasks) return; duke@435: _num_tasks--; duke@435: for (; index < _num_tasks; index++) { duke@435: _tasks[index] = _tasks[index+1]; duke@435: } duke@435: } duke@435: duke@435: TimeMillisUpdateTask* TimeMillisUpdateTask::_task = NULL; duke@435: duke@435: void TimeMillisUpdateTask::task() { duke@435: os::update_global_time(); duke@435: } duke@435: duke@435: void TimeMillisUpdateTask::engage() { duke@435: assert(_task == NULL, "init twice?"); duke@435: os::update_global_time(); // initial update duke@435: os::enable_global_time(); duke@435: _task = new TimeMillisUpdateTask(CacheTimeMillisGranularity); duke@435: _task->enroll(); duke@435: } duke@435: duke@435: void TimeMillisUpdateTask::disengage() { duke@435: assert(_task != NULL, "uninit twice?"); duke@435: os::disable_global_time(); duke@435: _task->disenroll(); duke@435: delete _task; duke@435: _task = NULL; duke@435: }