7127792: Add the ability to change an existing PeriodicTask's execution interval

Enables dynamic enrollment / disenrollment from the PeriodicTasks in WatcherThread.

Reviewed-by: dholmes, mgronlun
This commit is contained in:
Rickard Bäckman 2012-10-04 14:55:57 +02:00
parent 61a5a58cb1
commit e1d995ab86
6 changed files with 162 additions and 92 deletions

View file

@ -61,7 +61,7 @@ void PeriodicTask::print_intervals() {
}
#endif
void PeriodicTask::real_time_tick(size_t delay_time) {
void PeriodicTask::real_time_tick(int delay_time) {
#ifndef PRODUCT
if (ProfilerCheckIntervals) {
_ticks++;
@ -73,19 +73,39 @@ void PeriodicTask::real_time_tick(size_t delay_time) {
_intervalHistogram[ms]++;
}
#endif
int orig_num_tasks = _num_tasks;
for(int index = 0; index < _num_tasks; index++) {
_tasks[index]->execute_if_pending(delay_time);
if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself
index--; // re-do current slot as it has changed
orig_num_tasks = _num_tasks;
{
MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
int orig_num_tasks = _num_tasks;
for(int index = 0; index < _num_tasks; index++) {
_tasks[index]->execute_if_pending(delay_time);
if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself
index--; // re-do current slot as it has changed
orig_num_tasks = _num_tasks;
}
}
}
}
int PeriodicTask::time_to_wait() {
MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
if (_num_tasks == 0) {
return 0; // sleep until shutdown or a task is enrolled
}
int delay = _tasks[0]->time_to_next_interval();
for (int index = 1; index < _num_tasks; index++) {
delay = MIN2(delay, _tasks[index]->time_to_next_interval());
}
return delay;
}
PeriodicTask::PeriodicTask(size_t interval_time) :
_counter(0), _interval(interval_time) {
_counter(0), _interval((int) interval_time) {
// Sanity check the interval time
assert(_interval >= PeriodicTask::min_interval &&
_interval <= PeriodicTask::max_interval &&
@ -94,33 +114,40 @@ PeriodicTask::PeriodicTask(size_t interval_time) :
}
PeriodicTask::~PeriodicTask() {
if (is_enrolled())
disenroll();
}
bool PeriodicTask::is_enrolled() const {
for(int index = 0; index < _num_tasks; index++)
if (_tasks[index] == this) return true;
return false;
disenroll();
}
void PeriodicTask::enroll() {
assert(WatcherThread::watcher_thread() == NULL, "dynamic enrollment of tasks not yet supported");
MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
if (_num_tasks == PeriodicTask::max_tasks)
if (_num_tasks == PeriodicTask::max_tasks) {
fatal("Overflow in PeriodicTask table");
}
_tasks[_num_tasks++] = this;
WatcherThread* thread = WatcherThread::watcher_thread();
if (thread) {
thread->unpark();
} else {
WatcherThread::start();
}
}
void PeriodicTask::disenroll() {
assert(WatcherThread::watcher_thread() == NULL ||
Thread::current() == WatcherThread::watcher_thread(),
"dynamic disenrollment currently only handled from WatcherThread from within task() method");
MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
int index;
for(index = 0; index < _num_tasks && _tasks[index] != this; index++);
if (index == _num_tasks) return;
for(index = 0; index < _num_tasks && _tasks[index] != this; index++)
;
if (index == _num_tasks) {
return;
}
_num_tasks--;
for (; index < _num_tasks; index++) {
_tasks[index] = _tasks[index+1];
}