--- a/hotspot/src/share/vm/runtime/thread.cpp Mon Nov 05 13:55:31 2012 -0800
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Oct 04 14:55:57 2012 +0200
@@ -1217,6 +1217,7 @@
// timer interrupts exists on the platform.
WatcherThread* WatcherThread::_watcher_thread = NULL;
+bool WatcherThread::_startable = false;
volatile bool WatcherThread::_should_terminate = false;
WatcherThread::WatcherThread() : Thread() {
@@ -1237,6 +1238,55 @@
}
}
+int WatcherThread::sleep() const {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+
+ // remaining will be zero if there are no tasks,
+ // causing the WatcherThread to sleep until a task is
+ // enrolled
+ int remaining = PeriodicTask::time_to_wait();
+ int time_slept = 0;
+
+ // we expect this to timeout - we only ever get unparked when
+ // we should terminate or when a new task has been enrolled
+ OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);
+
+ jlong time_before_loop = os::javaTimeNanos();
+
+ for (;;) {
+ bool timedout = PeriodicTask_lock->wait(Mutex::_no_safepoint_check_flag, remaining);
+ jlong now = os::javaTimeNanos();
+
+ if (remaining == 0) {
+ // if we didn't have any tasks we could have waited for a long time
+ // consider the time_slept zero and reset time_before_loop
+ time_slept = 0;
+ time_before_loop = now;
+ } else {
+ // need to recalulate since we might have new tasks in _tasks
+ time_slept = (int) ((now - time_before_loop) / 1000000);
+ }
+
+ // Change to task list or spurious wakeup of some kind
+ if (timedout || _should_terminate) {
+ break;
+ }
+
+ remaining = PeriodicTask::time_to_wait();
+ if (remaining == 0) {
+ // Last task was just disenrolled so loop around and wait until
+ // another task gets enrolled
+ continue;
+ }
+
+ remaining -= time_slept;
+ if (remaining <= 0)
+ break;
+ }
+
+ return time_slept;
+}
+
void WatcherThread::run() {
assert(this == watcher_thread(), "just checking");
@@ -1249,26 +1299,7 @@
// Calculate how long it'll be until the next PeriodicTask work
// should be done, and sleep that amount of time.
- size_t time_to_wait = PeriodicTask::time_to_wait();
-
- // we expect this to timeout - we only ever get unparked when
- // we should terminate
- {
- OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);
-
- jlong prev_time = os::javaTimeNanos();
- for (;;) {
- int res= _SleepEvent->park(time_to_wait);
- if (res == OS_TIMEOUT || _should_terminate)
- break;
- // spurious wakeup of some kind
- jlong now = os::javaTimeNanos();
- time_to_wait -= (now - prev_time) / 1000000;
- if (time_to_wait <= 0)
- break;
- prev_time = now;
- }
- }
+ int time_waited = sleep();
if (is_error_reported()) {
// A fatal error has happened, the error handler(VMError::report_and_die)
@@ -1298,13 +1329,7 @@
}
}
- PeriodicTask::real_time_tick(time_to_wait);
-
- // If we have no more tasks left due to dynamic disenrollment,
- // shut down the thread since we don't currently support dynamic enrollment
- if (PeriodicTask::num_tasks() == 0) {
- _should_terminate = true;
- }
+ PeriodicTask::real_time_tick(time_waited);
}
// Signal that it is terminated
@@ -1319,22 +1344,33 @@
}
void WatcherThread::start() {
- if (watcher_thread() == NULL) {
+ assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
+
+ if (watcher_thread() == NULL && _startable) {
_should_terminate = false;
// Create the single instance of WatcherThread
new WatcherThread();
}
}
+void WatcherThread::make_startable() {
+ assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
+ _startable = true;
+}
+
void WatcherThread::stop() {
+ {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ _should_terminate = true;
+ OrderAccess::fence(); // ensure WatcherThread sees update in main loop
+
+ WatcherThread* watcher = watcher_thread();
+ if (watcher != NULL)
+ watcher->unpark();
+ }
+
// it is ok to take late safepoints here, if needed
MutexLocker mu(Terminator_lock);
- _should_terminate = true;
- OrderAccess::fence(); // ensure WatcherThread sees update in main loop
-
- Thread* watcher = watcher_thread();
- if (watcher != NULL)
- watcher->_SleepEvent->unpark();
while(watcher_thread() != NULL) {
// This wait should make safepoint checks, wait without a timeout,
@@ -1352,6 +1388,11 @@
}
}
+void WatcherThread::unpark() {
+ MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ PeriodicTask_lock->notify();
+}
+
void WatcherThread::print_on(outputStream* st) const {
st->print("\"%s\" ", name());
Thread::print_on(st);
@@ -3658,12 +3699,18 @@
}
}
- // Start up the WatcherThread if there are any periodic tasks
- // NOTE: All PeriodicTasks should be registered by now. If they
- // aren't, late joiners might appear to start slowly (we might
- // take a while to process their first tick).
- if (PeriodicTask::num_tasks() > 0) {
- WatcherThread::start();
+ {
+ MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+ // Make sure the watcher thread can be started by WatcherThread::start()
+ // or by dynamic enrollment.
+ WatcherThread::make_startable();
+ // Start up the WatcherThread if there are any periodic tasks
+ // NOTE: All PeriodicTasks should be registered by now. If they
+ // aren't, late joiners might appear to start slowly (we might
+ // take a while to process their first tick).
+ if (PeriodicTask::num_tasks() > 0) {
+ WatcherThread::start();
+ }
}
// Give os specific code one last chance to start