Bug 919638 - Followup: unbreak compiling without NSPR. (r=pnkfelix)
☠☠ backed out by f29ecd0b9c99 ☠ ☠
authorShu-yu Guo <shu@rfrn.org>
Fri, 10 Jan 2014 17:12:17 -0800
changeset 163020 ab1d9c6b581a8d7d4410075d66772adfee089078
parent 163019 5cae5d9ef313aded50e3ed3023a07afdd73f6cd0
child 163021 78c499a96bd072f038bc4f216c354f4c324a7633
push id25979
push usercbook@mozilla.com
push dateMon, 13 Jan 2014 11:46:02 +0000
treeherdermozilla-central@ea6657f1d682 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspnkfelix
bugs919638
milestone29.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 919638 - Followup: unbreak compiling without NSPR. (r=pnkfelix)
js/src/vm/Monitor.h
js/src/vm/ThreadPool.cpp
js/src/vm/ThreadPool.h
--- a/js/src/vm/Monitor.h
+++ b/js/src/vm/Monitor.h
@@ -28,19 +28,18 @@ class Monitor
 {
   protected:
     friend class AutoLockMonitor;
     friend class AutoUnlockMonitor;
 
     PRLock *lock_;
     PRCondVar *condVar_;
 
-
-    void assertIsHoldingLock() const {
-        PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(lock_);
+    bool isFor(Monitor &monitor) const {
+        return lock_ == monitor.lock_;
     }
 
   public:
     Monitor()
       : lock_(nullptr),
         condVar_(nullptr)
     { }
 
@@ -75,33 +74,53 @@ class AutoLockMonitor
 #endif
 
     ~AutoLockMonitor() {
 #ifdef JS_THREADSAFE
         PR_Unlock(monitor.lock_);
 #endif
     }
 
-    void wait() {
+    void wait(PRCondVar *condVar) {
 #ifdef JS_THREADSAFE
         mozilla::DebugOnly<PRStatus> status =
-          PR_WaitCondVar(monitor.condVar_, PR_INTERVAL_NO_TIMEOUT);
-        JS_ASSERT(status == PR_SUCCESS);
+          PR_WaitCondVar(condVar, PR_INTERVAL_NO_TIMEOUT);
+        MOZ_ASSERT(status == PR_SUCCESS);
+#endif
+    }
+
+    void wait() {
+#ifdef JS_THREADSAFE
+        wait(monitor.condVar_);
+#endif
+    }
+
+    void notify(PRCondVar *condVar) {
+#ifdef JS_THREADSAFE
+        mozilla::DebugOnly<PRStatus> status = PR_NotifyCondVar(condVar);
+        MOZ_ASSERT(status == PR_SUCCESS);
 #endif
     }
 
     void notify() {
 #ifdef JS_THREADSAFE
-        PR_NotifyCondVar(monitor.condVar_);
+        notify(monitor.condVar_);
+#endif
+    }
+
+    void notifyAll(PRCondVar *condVar) {
+#ifdef JS_THREADSAFE
+        mozilla::DebugOnly<PRStatus> status = PR_NotifyAllCondVar(monitor.condVar_);
+        MOZ_ASSERT(status == PR_SUCCESS);
 #endif
     }
 
     void notifyAll() {
 #ifdef JS_THREADSAFE
-        PR_NotifyAllCondVar(monitor.condVar_);
+        notifyAll(monitor.condVar_);
 #endif
     }
 };
 
 class AutoUnlockMonitor
 {
   private:
 #ifdef JS_THREADSAFE
--- a/js/src/vm/ThreadPool.cpp
+++ b/js/src/vm/ThreadPool.cpp
@@ -107,17 +107,17 @@ class js::ThreadPoolWorker : public Thre
       : ThreadPoolBaseWorker(workerId, pool),
         state_(CREATED)
     { }
 
     // Invoked from main thread; signals worker to start.
     bool start();
 
     // Invoked from main thread; signals the worker loop to return.
-    void terminate();
+    void terminate(AutoLockMonitor &lock);
 };
 
 // ThreadPoolMainWorker
 //
 // This class abstracts the main thread as a worker thread with a private
 // queue to allow for work stealing.
 
 class js::ThreadPoolMainWorker : public ThreadPoolBaseWorker
@@ -275,17 +275,17 @@ ThreadPoolWorker::run()
     for (;;) {
         // Wait for work to arrive or for us to terminate.
         {
             AutoLockMonitor lock(*pool_);
             while (state_ == ACTIVE && !pool_->hasWork())
                 lock.wait();
 
             if (state_ == TERMINATED) {
-                pool_->join();
+                pool_->join(lock);
                 return;
             }
 
             pool_->activeWorkers_++;
         }
 
         ParallelJob *job = pool_->job();
         uint16_t sliceId;
@@ -294,26 +294,26 @@ ThreadPoolWorker::run()
                 pool_->abortJob();
                 break;
             }
         }
 
         // Join the pool.
         {
             AutoLockMonitor lock(*pool_);
-            pool_->join();
+            pool_->join(lock);
         }
     }
 }
 
 void
-ThreadPoolWorker::terminate()
+ThreadPoolWorker::terminate(AutoLockMonitor &lock)
 {
+    MOZ_ASSERT(lock.isFor(*this));
     MOZ_ASSERT(state_ != TERMINATED);
-    pool_->assertIsHoldingLock();
     state_ = TERMINATED;
 }
 
 void
 ThreadPoolMainWorker::executeJob()
 {
     ParallelJob *job = pool_->job();
     uint16_t sliceId;
@@ -364,18 +364,20 @@ ThreadPool::ThreadPool(JSRuntime *rt)
     stolenSlices_(0),
 #endif
     pendingSlices_(0)
 { }
 
 ThreadPool::~ThreadPool()
 {
     terminateWorkers();
+#ifdef JS_THREADSAFE
     if (joinBarrier_)
         PR_DestroyCondVar(joinBarrier_);
+#endif
 }
 
 bool
 ThreadPool::init()
 {
 #ifdef JS_THREADSAFE
     if (!Monitor::init())
         return false;
@@ -462,61 +464,54 @@ ThreadPool::terminateWorkersAndReportOOM
 void
 ThreadPool::terminateWorkers()
 {
     if (workers_.length() > 0) {
         AutoLockMonitor lock(*this);
 
         // Signal to the workers they should quit.
         for (uint32_t i = 0; i < workers_.length(); i++)
-            workers_[i]->terminate();
+            workers_[i]->terminate(lock);
 
         // Wake up all the workers. Set the number of active workers to the
         // current number of workers so we can make sure they all join.
         activeWorkers_ = workers_.length();
         lock.notifyAll();
 
         // Wait for all workers to join.
-        waitForWorkers();
+        waitForWorkers(lock);
 
         while (workers_.length() > 0)
             js_delete(workers_.popCopy());
     }
 
     js_delete(mainWorker_);
 }
 
 void
 ThreadPool::terminate()
 {
     terminateWorkers();
 }
 
 void
-ThreadPool::join()
+ThreadPool::join(AutoLockMonitor &lock)
 {
-#ifdef JS_THREADSAFE
-    assertIsHoldingLock();
+    MOZ_ASSERT(lock.isFor(*this));
     if (--activeWorkers_ == 0)
-        PR_NotifyCondVar(joinBarrier_);
-#endif
+        lock.notify(joinBarrier_);
 }
 
 void
-ThreadPool::waitForWorkers()
+ThreadPool::waitForWorkers(AutoLockMonitor &lock)
 {
-#ifdef JS_THREADSAFE
-    assertIsHoldingLock();
-    while (activeWorkers_ > 0) {
-        mozilla::DebugOnly<PRStatus> status =
-            PR_WaitCondVar(joinBarrier_, PR_INTERVAL_NO_TIMEOUT);
-        MOZ_ASSERT(status == PR_SUCCESS);
-    }
+    MOZ_ASSERT(lock.isFor(*this));
+    while (activeWorkers_ > 0)
+        lock.wait(joinBarrier_);
     job_ = nullptr;
-#endif
 }
 
 ParallelResult
 ThreadPool::executeJob(JSContext *cx, ParallelJob *job, uint16_t numSlices)
 {
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime_));
     MOZ_ASSERT(activeWorkers_ == 0);
     MOZ_ASSERT(!hasWork());
@@ -566,17 +561,17 @@ ThreadPool::executeJob(JSContext *cx, Pa
     mainWorker_->isActive = true;
     mainWorker_->executeJob();
     mainWorker_->isActive = false;
 
     // Wait for all threads to join. While there are no pending slices at this
     // point, the slices themselves may not be finished processing.
     {
         AutoLockMonitor lock(*this);
-        waitForWorkers();
+        waitForWorkers(lock);
     }
 
     // Everything went swimmingly. Give yourself a pat on the back.
     return TP_SUCCESS;
 }
 
 void
 ThreadPool::abortJob()
--- a/js/src/vm/ThreadPool.h
+++ b/js/src/vm/ThreadPool.h
@@ -103,18 +103,18 @@ class ThreadPool : public Monitor
 #endif
 
     // Number of pending slices in the current job.
     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> pendingSlices_;
 
     bool lazyStartWorkers(JSContext *cx);
     void terminateWorkers();
     void terminateWorkersAndReportOOM(JSContext *cx);
-    void join();
-    void waitForWorkers();
+    void join(AutoLockMonitor &lock);
+    void waitForWorkers(AutoLockMonitor &lock);
 
   public:
     ThreadPool(JSRuntime *rt);
     ~ThreadPool();
 
     bool init();
 
     // Return number of worker threads in the pool, not counting the main thread.