Backed out changeset 67d13c5fcf84 (bug 956899)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 28 May 2016 01:39:00 +0200
changeset 372399 3c86f1e4bbc95042068ec7b1e2246ab54239e1ce
parent 372398 a3a3aa23f4ef145bdc30278e092b77676e00babf
child 372400 764ab2ad75e784d0175f6645c1c2fca4816863af
push id19519
push userbmo:rail@mozilla.com
push dateSat, 28 May 2016 13:01:27 +0000
bugs956899
milestone49.0a1
backs out67d13c5fcf841e33734c0568fffa9f7686fd264f
Backed out changeset 67d13c5fcf84 (bug 956899)
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -74,19 +74,16 @@
 #include "js/GCAPI.h"
 #include "js/Initialization.h"
 #include "js/StructuredClone.h"
 #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 "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"
@@ -165,22 +162,22 @@ struct ShellRuntime
 #ifdef SPIDERMONKEY_PROMISE
     JS::PersistentRootedValue promiseRejectionTrackerCallback;
     JS::PersistentRooted<JobQueue> jobQueue;
 #endif // SPIDERMONKEY_PROMISE
 
     /*
      * Watchdog thread state.
      */
-    Mutex watchdogLock;
-    ConditionVariable watchdogWakeup;
+    PRLock* watchdogLock;
+    PRCondVar* watchdogWakeup;
     PRThread* watchdogThread;
     Maybe<TimeStamp> watchdogTimeout;
 
-    ConditionVariable sleepWakeup;
+    PRCondVar* sleepWakeup;
 
     int exitCode;
     bool quitting;
     bool gotError;
 };
 
 // Shell state set once at startup.
 static bool enableCodeCoverage = false;
@@ -214,16 +211,19 @@ static bool OOM_printAllocationCount = f
 
 // Shell state this is only accessed on the main thread.
 bool jsCachingEnabled = false;
 mozilla::Atomic<bool> jsCacheOpened(false);
 
 static bool
 SetTimeoutValue(JSContext* cx, double t);
 
+static bool
+InitWatchdog(JSRuntime* rt);
+
 static void
 KillWatchdog(JSRuntime *rt);
 
 static bool
 ScheduleWatchdog(JSRuntime* rt, double t);
 
 static void
 CancelExecution(JSRuntime* rt);
@@ -310,17 +310,20 @@ 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
+    watchdogLock(nullptr),
+    watchdogWakeup(nullptr),
     watchdogThread(nullptr),
+    sleepWakeup(nullptr),
     exitCode(0),
     quitting(false),
     gotError(false)
 {}
 
 static ShellRuntime*
 GetShellRuntime(JSRuntime *rt)
 {
@@ -2928,16 +2931,22 @@ WorkerMain(void* arg)
 
     sr->isWorker = true;
     JS_SetRuntimePrivate(rt, sr.get());
     JS_SetFutexCanWait(rt);
     JS_SetErrorReporter(rt, my_ErrorReporter);
     JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
     SetWorkerRuntimeOptions(rt);
 
+    if (!InitWatchdog(rt)) {
+        JS_DestroyRuntime(rt);
+        js_delete(input);
+        return;
+    }
+
     JSContext* cx = NewContext(rt);
     if (!cx) {
         JS_DestroyRuntime(rt);
         js_delete(input);
         return;
     }
 
 #ifdef SPIDERMONKEY_PROMISE
@@ -3087,125 +3096,151 @@ Sleep_fn(JSContext* cx, unsigned argc, V
         duration = TimeDuration::FromSeconds(Max(0.0, t_secs));
 
         /* NB: The next condition also filter out NaNs. */
         if (duration > MAX_TIMEOUT_INTERVAL) {
             JS_ReportError(cx, "Excessive sleep interval");
             return false;
         }
     }
-    {
-        LockGuard<Mutex> guard(sr->watchdogLock);
-        TimeStamp toWakeup = TimeStamp::Now() + duration;
-        for (;;) {
-            sr->sleepWakeup.wait_for(guard, duration);
-            if (sr->serviceInterrupt)
-                break;
-            auto now = TimeStamp::Now();
-            if (now >= toWakeup)
-                break;
-            duration = toWakeup - now;
-        }
-    }
+    PR_Lock(sr->watchdogLock);
+    TimeStamp toWakeup = TimeStamp::Now() + duration;
+    for (;;) {
+        PR_WaitCondVar(sr->sleepWakeup, DurationToPRInterval(duration));
+        if (sr->serviceInterrupt)
+            break;
+        auto now = TimeStamp::Now();
+        if (now >= toWakeup)
+            break;
+        duration = toWakeup - now;
+    }
+    PR_Unlock(sr->watchdogLock);
     args.rval().setUndefined();
     return !sr->serviceInterrupt;
 }
 
+static bool
+InitWatchdog(JSRuntime* rt)
+{
+    ShellRuntime* sr = GetShellRuntime(rt);
+    MOZ_ASSERT(!sr->watchdogThread);
+    sr->watchdogLock = PR_NewLock();
+    if (sr->watchdogLock) {
+        sr->watchdogWakeup = PR_NewCondVar(sr->watchdogLock);
+        if (sr->watchdogWakeup) {
+            sr->sleepWakeup = PR_NewCondVar(sr->watchdogLock);
+            if (sr->sleepWakeup)
+                return true;
+            PR_DestroyCondVar(sr->watchdogWakeup);
+        }
+        PR_DestroyLock(sr->watchdogLock);
+    }
+    return false;
+}
+
 static void
 KillWatchdog(JSRuntime* rt)
 {
     ShellRuntime* sr = GetShellRuntime(rt);
     PRThread* thread;
 
-    {
-        LockGuard<Mutex> guard(sr->watchdogLock);
-        thread = sr->watchdogThread;
-        if (thread) {
-            /*
-             * The watchdog thread is running, tell it to terminate waking it up
-             * if necessary.
-             */
-            sr->watchdogThread = nullptr;
-            sr->watchdogWakeup.notify_one();
-        }
-    }
+    PR_Lock(sr->watchdogLock);
+    thread = sr->watchdogThread;
+    if (thread) {
+        /*
+         * The watchdog thread is running, tell it to terminate waking it up
+         * if necessary.
+         */
+        sr->watchdogThread = nullptr;
+        PR_NotifyCondVar(sr->watchdogWakeup);
+    }
+    PR_Unlock(sr->watchdogLock);
     if (thread)
         PR_JoinThread(thread);
+    PR_DestroyCondVar(sr->sleepWakeup);
+    PR_DestroyCondVar(sr->watchdogWakeup);
+    PR_DestroyLock(sr->watchdogLock);
 }
 
 static void
 WatchdogMain(void* arg)
 {
     PR_SetCurrentThreadName("JS Watchdog");
 
     JSRuntime* rt = (JSRuntime*) arg;
     ShellRuntime* sr = GetShellRuntime(rt);
 
-    LockGuard<Mutex> guard(sr->watchdogLock);
+    PR_Lock(sr->watchdogLock);
     while (sr->watchdogThread) {
         auto now = TimeStamp::Now();
         if (sr->watchdogTimeout.isSome() && 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);
-            }
+            PR_Unlock(sr->watchdogLock);
+            CancelExecution(rt);
+            PR_Lock(sr->watchdogLock);
 
             /* Wake up any threads doing sleep. */
-            sr->sleepWakeup.notify_all();
+            PR_NotifyAllCondVar(sr->sleepWakeup);
         } else {
             if (sr->watchdogTimeout.isSome()) {
                 /*
                  * Time hasn't expired yet. Simulate an interrupt callback
                  * which doesn't abort execution.
                  */
                 JS_RequestInterruptCallback(rt);
             }
 
             TimeDuration sleepDuration = sr->watchdogTimeout.isSome()
                                          ? TimeDuration::FromSeconds(0.1)
                                          : TimeDuration::Forever();
-            sr->watchdogWakeup.wait_for(guard, sleepDuration);
+            mozilla::DebugOnly<PRStatus> status =
+              PR_WaitCondVar(sr->watchdogWakeup, DurationToPRInterval(sleepDuration));
+            MOZ_ASSERT(status == PR_SUCCESS);
         }
     }
+    PR_Unlock(sr->watchdogLock);
 }
 
 static bool
 ScheduleWatchdog(JSRuntime* rt, double t)
 {
     ShellRuntime* sr = GetShellRuntime(rt);
 
     if (t <= 0) {
-        LockGuard<Mutex> guard(sr->watchdogLock);
+        PR_Lock(sr->watchdogLock);
         sr->watchdogTimeout = Nothing();
+        PR_Unlock(sr->watchdogLock);
         return true;
     }
 
     auto interval = TimeDuration::FromSeconds(t);
     auto timeout = TimeStamp::Now() + interval;
-    LockGuard<Mutex> guard(sr->watchdogLock);
+    PR_Lock(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)
+        if (!sr->watchdogThread) {
+            PR_Unlock(sr->watchdogLock);
             return false;
+        }
     } else if (sr->watchdogTimeout.isNothing() || timeout < sr->watchdogTimeout.value()) {
-         sr->watchdogWakeup.notify_one();
+         PR_NotifyCondVar(sr->watchdogWakeup);
     }
     sr->watchdogTimeout = Some(timeout);
+    PR_Unlock(sr->watchdogLock);
     return true;
 }
 
 static void
 KillWorkerThreads()
 {
     MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
 
@@ -7390,16 +7425,19 @@ main(int argc, char** argv, char** envp)
 
     JS_SetNativeStackQuota(rt, gMaxStackSize);
 
     JS::dbg::SetDebuggerMallocSizeOf(rt, moz_malloc_size_of);
 
     if (!offThreadState.init())
         return 1;
 
+    if (!InitWatchdog(rt))
+        return 1;
+
     cx = NewContext(rt);
     if (!cx)
         return 1;
 
 #ifdef SPIDERMONKEY_PROMISE
     sr->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
     JS::SetEnqueuePromiseJobCallback(rt, ShellEnqueuePromiseJobCallback);
 #endif // SPIDERMONKEY_PROMISE