src/share/vm/runtime/thread.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/runtime/thread.cpp

src/share/vm/runtime/thread.cpp

Print this page

        

*** 1160,1169 **** --- 1160,1170 ---- // The watcher thread exists to simulate timer interrupts. It should // be replaced by an abstraction over whatever native support for // timer interrupts exists on the platform. WatcherThread* WatcherThread::_watcher_thread = NULL; + bool WatcherThread::_startable = false; volatile bool WatcherThread::_should_terminate = false; WatcherThread::WatcherThread() : Thread() { assert(watcher_thread() == NULL, "we can only allocate one WatcherThread"); if (os::create_thread(this, os::watcher_thread)) {
*** 1180,1189 **** --- 1181,1239 ---- os::start_thread(this); } } } + jint 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 + jint remaining = PeriodicTask::time_to_wait(); + jint 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 = (jint) ((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"); this->record_stack_base_and_size(); this->initialize_thread_local_storage();
*** 1192,1221 **** assert(watcher_thread() == Thread::current(), "thread consistency check"); assert(watcher_thread() == this, "thread consistency check"); // 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; ! } ! } if (is_error_reported()) { // A fatal error has happened, the error handler(VMError::report_and_die) // should abort JVM after creating an error log file. However in some // rare cases, the error handler itself might deadlock. Here we try to --- 1242,1252 ---- assert(watcher_thread() == Thread::current(), "thread consistency check"); assert(watcher_thread() == this, "thread consistency check"); // Calculate how long it'll be until the next PeriodicTask work // should be done, and sleep that amount of time. ! jint time_waited = sleep(); if (is_error_reported()) { // A fatal error has happened, the error handler(VMError::report_and_die) // should abort JVM after creating an error log file. However in some // rare cases, the error handler itself might deadlock. Here we try to
*** 1241,1257 **** // ShowMessageBoxOnError when it is ready to abort. os::sleep(this, 5 * 1000, false); } } ! 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; ! } } // Signal that it is terminated { MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); --- 1272,1282 ---- // ShowMessageBoxOnError when it is ready to abort. os::sleep(this, 5 * 1000, false); } } ! PeriodicTask::real_time_tick(time_waited); } // Signal that it is terminated { MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag);
*** 1262,1287 **** // Thread destructor usually does this.. ThreadLocalStorage::set_thread(NULL); } void WatcherThread::start() { ! if (watcher_thread() == NULL) { _should_terminate = false; // Create the single instance of WatcherThread new WatcherThread(); } } void WatcherThread::stop() { ! // 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, // and wait as a suspend-equivalent condition. // --- 1287,1323 ---- // Thread destructor usually does this.. ThreadLocalStorage::set_thread(NULL); } void WatcherThread::start() { ! 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); while(watcher_thread() != NULL) { // This wait should make safepoint checks, wait without a timeout, // and wait as a suspend-equivalent condition. //
*** 1295,1304 **** --- 1331,1345 ---- Terminator_lock->wait(!Mutex::_no_safepoint_check_flag, 0, Mutex::_as_suspend_equivalent_flag); } } + 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); st->cr(); }
*** 3561,3577 **** --- 3602,3624 ---- if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; } } + { + 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 os::init_3(); create_vm_timer.end();
src/share/vm/runtime/thread.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File