diff -r 655c5b5f7486 -r bd0d881cf1c5 hotspot/src/share/vm/runtime/thread.cpp --- 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