comparison src/share/vm/runtime/task.cpp @ 6939:c284cf4781f0

7127792: Add the ability to change an existing PeriodicTask's execution interval Summary: Enables dynamic enrollment / disenrollment from the PeriodicTasks in WatcherThread. Reviewed-by: dholmes, mgronlun
author rbackman
date Thu, 04 Oct 2012 14:55:57 +0200
parents f08d439fab8c
children f34d701e952e
comparison
equal deleted inserted replaced
6938:8940ddc1036f 6939:c284cf4781f0
59 } 59 }
60 } 60 }
61 } 61 }
62 #endif 62 #endif
63 63
64 void PeriodicTask::real_time_tick(size_t delay_time) { 64 void PeriodicTask::real_time_tick(int delay_time) {
65 #ifndef PRODUCT 65 #ifndef PRODUCT
66 if (ProfilerCheckIntervals) { 66 if (ProfilerCheckIntervals) {
67 _ticks++; 67 _ticks++;
68 _timer.stop(); 68 _timer.stop();
69 int ms = (int)(_timer.seconds() * 1000.0); 69 int ms = (int)(_timer.seconds() * 1000.0);
71 _timer.start(); 71 _timer.start();
72 if (ms >= PeriodicTask::max_interval) ms = PeriodicTask::max_interval - 1; 72 if (ms >= PeriodicTask::max_interval) ms = PeriodicTask::max_interval - 1;
73 _intervalHistogram[ms]++; 73 _intervalHistogram[ms]++;
74 } 74 }
75 #endif 75 #endif
76 int orig_num_tasks = _num_tasks; 76
77 for(int index = 0; index < _num_tasks; index++) { 77 {
78 _tasks[index]->execute_if_pending(delay_time); 78 MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
79 if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself 79 int orig_num_tasks = _num_tasks;
80 index--; // re-do current slot as it has changed 80
81 orig_num_tasks = _num_tasks; 81 for(int index = 0; index < _num_tasks; index++) {
82 _tasks[index]->execute_if_pending(delay_time);
83 if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself
84 index--; // re-do current slot as it has changed
85 orig_num_tasks = _num_tasks;
86 }
82 } 87 }
83 } 88 }
84 } 89 }
85 90
91 int PeriodicTask::time_to_wait() {
92 MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
93 NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
94
95 if (_num_tasks == 0) {
96 return 0; // sleep until shutdown or a task is enrolled
97 }
98
99 int delay = _tasks[0]->time_to_next_interval();
100 for (int index = 1; index < _num_tasks; index++) {
101 delay = MIN2(delay, _tasks[index]->time_to_next_interval());
102 }
103 return delay;
104 }
105
86 106
87 PeriodicTask::PeriodicTask(size_t interval_time) : 107 PeriodicTask::PeriodicTask(size_t interval_time) :
88 _counter(0), _interval(interval_time) { 108 _counter(0), _interval((int) interval_time) {
89 // Sanity check the interval time 109 // Sanity check the interval time
90 assert(_interval >= PeriodicTask::min_interval && 110 assert(_interval >= PeriodicTask::min_interval &&
91 _interval <= PeriodicTask::max_interval && 111 _interval <= PeriodicTask::max_interval &&
92 _interval % PeriodicTask::interval_gran == 0, 112 _interval % PeriodicTask::interval_gran == 0,
93 "improper PeriodicTask interval time"); 113 "improper PeriodicTask interval time");
94 } 114 }
95 115
96 PeriodicTask::~PeriodicTask() { 116 PeriodicTask::~PeriodicTask() {
97 if (is_enrolled()) 117 disenroll();
98 disenroll();
99 }
100
101 bool PeriodicTask::is_enrolled() const {
102 for(int index = 0; index < _num_tasks; index++)
103 if (_tasks[index] == this) return true;
104 return false;
105 } 118 }
106 119
107 void PeriodicTask::enroll() { 120 void PeriodicTask::enroll() {
108 assert(WatcherThread::watcher_thread() == NULL, "dynamic enrollment of tasks not yet supported"); 121 MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
122 NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
109 123
110 if (_num_tasks == PeriodicTask::max_tasks) 124 if (_num_tasks == PeriodicTask::max_tasks) {
111 fatal("Overflow in PeriodicTask table"); 125 fatal("Overflow in PeriodicTask table");
126 }
112 _tasks[_num_tasks++] = this; 127 _tasks[_num_tasks++] = this;
128
129 WatcherThread* thread = WatcherThread::watcher_thread();
130 if (thread) {
131 thread->unpark();
132 } else {
133 WatcherThread::start();
134 }
113 } 135 }
114 136
115 void PeriodicTask::disenroll() { 137 void PeriodicTask::disenroll() {
116 assert(WatcherThread::watcher_thread() == NULL || 138 MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ?
117 Thread::current() == WatcherThread::watcher_thread(), 139 NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
118 "dynamic disenrollment currently only handled from WatcherThread from within task() method");
119 140
120 int index; 141 int index;
121 for(index = 0; index < _num_tasks && _tasks[index] != this; index++); 142 for(index = 0; index < _num_tasks && _tasks[index] != this; index++)
122 if (index == _num_tasks) return; 143 ;
144
145 if (index == _num_tasks) {
146 return;
147 }
148
123 _num_tasks--; 149 _num_tasks--;
150
124 for (; index < _num_tasks; index++) { 151 for (; index < _num_tasks; index++) {
125 _tasks[index] = _tasks[index+1]; 152 _tasks[index] = _tasks[index+1];
126 } 153 }
127 } 154 }