src/share/vm/runtime/thread.cpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -1194,12 +1194,20 @@
     }
   }
 }
 
 int WatcherThread::sleep() const {
+  // The WatcherThread does not honor the safepoint protocol for
+  // PeriodicTask_lock in order to provide more consistent task
+  // execution timing.
   MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
 
+  if (_should_terminate) {
+    // check for termination before we do any housekeeping or wait
+    return 0;  // we did not sleep.
+  }
+
   // 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;

@@ -1208,12 +1216,13 @@
   // 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);
+  while (true) {
+    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

@@ -1250,11 +1259,11 @@
 
   this->record_stack_base_and_size();
   this->initialize_thread_local_storage();
   this->set_native_thread_name(this->name());
   this->set_active_handles(JNIHandleBlock::allocate_block());
-  while (!_should_terminate) {
+  while (true) {
     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.

@@ -1286,10 +1295,15 @@
         // ShowMessageBoxOnError when it is ready to abort.
         os::sleep(this, 5 * 1000, false);
       }
     }
 
+    if (_should_terminate) {
+      // check for termination before posting the next tick
+      break;
+    }
+
     PeriodicTask::real_time_tick(time_waited);
   }
 
   // Signal that it is terminated
   {

@@ -1316,31 +1330,24 @@
   assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
   _startable = true;
 }
 
 void WatcherThread::stop() {
-  // Get the PeriodicTask_lock if we can. If we cannot, then the
-  // WatcherThread is using it and we don't want to block on that lock
-  // here because that might cause a safepoint deadlock depending on
-  // what the current WatcherThread tasks are doing.
-  bool have_lock = PeriodicTask_lock->try_lock();
-
+  {
+    // Follow normal safepoint aware lock enter protocol since the
+    // WatcherThread is stopped by another JavaThread.
+    MutexLocker ml(PeriodicTask_lock);
   _should_terminate = true;
   OrderAccess::fence();  // ensure WatcherThread sees update in main loop
 
-  if (have_lock) {
     WatcherThread* watcher = watcher_thread();
     if (watcher != NULL) {
-      // If we managed to get the lock, then we should unpark the
-      // WatcherThread so that it can see we want it to stop.
+      // unpark the WatcherThread so it can see that it should terminate
       watcher->unpark();
     }
-
-    PeriodicTask_lock->unlock();
   }
 
-  // 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.

@@ -1356,13 +1363,11 @@
                           Mutex::_as_suspend_equivalent_flag);
   }
 }
 
 void WatcherThread::unpark() {
-  MutexLockerEx ml(PeriodicTask_lock->owned_by_self()
-                   ? NULL
-                   : PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
+  assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
   PeriodicTask_lock->notify();
 }
 
 void WatcherThread::print_on(outputStream* st) const {
   st->print("\"%s\" ", name());

@@ -3555,12 +3560,12 @@
       CLEAR_PENDING_EXCEPTION;
     }
   }
 
   {
-    MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);
-    // Make sure the watcher thread can be started by WatcherThread::start()
+    MutexLocker ml(PeriodicTask_lock);
+    // Make sure the WatcherThread 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