Bug 956899 - Use js::Thread for JS shell watchdog thread; r=jandem
authorTerrence Cole <terrence@mozilla.com>
Sat, 28 May 2016 16:10:15 +0200
changeset 340450 132e391ed5e588241227dfb48083dcd57ac3142f
parent 340449 df7f3f8416c5b24f1ea6bfad1015211d6bace955
child 340451 7c65a26181d971116a4ce891635b531832d5d28c
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs956899
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 956899 - Use js::Thread for JS shell watchdog thread; r=jandem
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -77,16 +77,17 @@
 #include "js/TrackedOptimizationInfo.h"
 #include "perf/jsperf.h"
 #include "shell/jsoptparse.h"
 #include "shell/jsshell.h"
 #include "shell/OSObject.h"
 #include "threading/ConditionVariable.h"
 #include "threading/LockGuard.h"
 #include "threading/Mutex.h"
+#include "threading/Thread.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/Compression.h"
 #include "vm/Debugger.h"
 #include "vm/HelperThreads.h"
 #include "vm/Monitor.h"
 #include "vm/Shape.h"
 #include "vm/SharedArrayObject.h"
 #include "vm/StringBuffer.h"
@@ -167,17 +168,17 @@ struct ShellRuntime
     JS::PersistentRooted<JobQueue> jobQueue;
 #endif // SPIDERMONKEY_PROMISE
 
     /*
      * Watchdog thread state.
      */
     Mutex watchdogLock;
     ConditionVariable watchdogWakeup;
-    PRThread* watchdogThread;
+    Maybe<Thread> watchdogThread;
     Maybe<TimeStamp> watchdogTimeout;
 
     ConditionVariable sleepWakeup;
 
     int exitCode;
     bool quitting;
 };
 
@@ -319,17 +320,16 @@ ShellRuntime::ShellRuntime(JSRuntime* rt
     serviceInterrupt(false),
     haveInterruptFunc(false),
     interruptFunc(rt, NullValue()),
     lastWarningEnabled(false),
     lastWarning(rt, NullValue()),
 #ifdef SPIDERMONKEY_PROMISE
     promiseRejectionTrackerCallback(rt, NullValue()),
 #endif // SPIDERMONKEY_PROMISE
-    watchdogThread(nullptr),
     exitCode(0),
     quitting(false)
 {}
 
 static ShellRuntime*
 GetShellRuntime(JSRuntime *rt)
 {
     ShellRuntime* sr = static_cast<ShellRuntime*>(JS_GetRuntimePrivate(rt));
@@ -3128,68 +3128,65 @@ Sleep_fn(JSContext* cx, unsigned argc, V
     args.rval().setUndefined();
     return !sr->serviceInterrupt;
 }
 
 static void
 KillWatchdog(JSRuntime* rt)
 {
     ShellRuntime* sr = GetShellRuntime(rt);
-    PRThread* thread;
+    Maybe<Thread> thread;
 
     {
         LockGuard<Mutex> guard(sr->watchdogLock);
-        thread = sr->watchdogThread;
+        Swap(sr->watchdogThread, thread);
         if (thread) {
-            /*
-             * The watchdog thread is running, tell it to terminate waking it up
-             * if necessary.
-             */
-            sr->watchdogThread = nullptr;
+            // The watchdog thread becoming Nothing is its signal to exit.
             sr->watchdogWakeup.notify_one();
         }
     }
     if (thread)
-        PR_JoinThread(thread);
+        thread->join();
+
+    MOZ_ASSERT(!sr->watchdogThread);
 }
 
 static void
-WatchdogMain(void* arg)
-{
-    PR_SetCurrentThreadName("JS Watchdog");
-
-    JSRuntime* rt = (JSRuntime*) arg;
+WatchdogMain(JSRuntime* rt)
+{
+    ThisThread::SetName("JS Watchdog");
+
     ShellRuntime* sr = GetShellRuntime(rt);
 
     LockGuard<Mutex> guard(sr->watchdogLock);
     while (sr->watchdogThread) {
         auto now = TimeStamp::Now();
-        if (sr->watchdogTimeout.isSome() && now >= sr->watchdogTimeout.value()) {
+        if (sr->watchdogTimeout && now >= sr->watchdogTimeout.value()) {
             /*
              * The timeout has just expired. Request an interrupt callback
              * outside the lock.
              */
             sr->watchdogTimeout = Nothing();
             {
                 UnlockGuard<Mutex> unlock(guard);
                 CancelExecution(rt);
             }
 
             /* Wake up any threads doing sleep. */
             sr->sleepWakeup.notify_all();
         } else {
-            if (sr->watchdogTimeout.isSome()) {
+            if (sr->watchdogTimeout) {
                 /*
                  * Time hasn't expired yet. Simulate an interrupt callback
                  * which doesn't abort execution.
                  */
                 JS_RequestInterruptCallback(rt);
             }
 
-            TimeDuration sleepDuration = sr->watchdogTimeout.isSome()
+            TimeDuration sleepDuration = sr->watchdogTimeout
                                          ? TimeDuration::FromSeconds(0.1)
                                          : TimeDuration::Forever();
             sr->watchdogWakeup.wait_for(guard, sleepDuration);
         }
     }
 }
 
 static bool
@@ -3202,27 +3199,19 @@ ScheduleWatchdog(JSRuntime* rt, double t
         sr->watchdogTimeout = Nothing();
         return true;
     }
 
     auto interval = TimeDuration::FromSeconds(t);
     auto timeout = TimeStamp::Now() + interval;
     LockGuard<Mutex> guard(sr->watchdogLock);
     if (!sr->watchdogThread) {
-        MOZ_ASSERT(sr->watchdogTimeout.isNothing());
-        sr->watchdogThread = PR_CreateThread(PR_USER_THREAD,
-                                          WatchdogMain,
-                                          rt,
-                                          PR_PRIORITY_NORMAL,
-                                          PR_GLOBAL_THREAD,
-                                          PR_JOINABLE_THREAD,
-                                          0);
-        if (!sr->watchdogThread)
-            return false;
-    } else if (sr->watchdogTimeout.isNothing() || timeout < sr->watchdogTimeout.value()) {
+        MOZ_ASSERT(!sr->watchdogTimeout);
+        sr->watchdogThread.emplace(WatchdogMain, rt);
+    } else if (!sr->watchdogTimeout || timeout < sr->watchdogTimeout.value()) {
          sr->watchdogWakeup.notify_one();
     }
     sr->watchdogTimeout = Some(timeout);
     return true;
 }
 
 static void
 KillWorkerThreads()