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