Bug 919638 - Followup: unbreak compiling without NSPR. (r=pnkfelix)
authorShu-yu Guo <shu@rfrn.org>
Fri, 10 Jan 2014 17:12:17 -0800
changeset 163025 7c3432eb049bfb7eb2052a7b23d3d9997ca699e9
parent 163024 f29ecd0b9c992d095da172fb8f526758bc8fb185
child 163026 046258beb9286f7ad22565f33e51c7757461cb84
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,21 +28,16 @@ class Monitor
 {
   protected:
     friend class AutoLockMonitor;
     friend class AutoUnlockMonitor;
 
     PRLock *lock_;
     PRCondVar *condVar_;
 
-
-    void assertIsHoldingLock() const {
-        PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(lock_);
-    }
-
   public:
     Monitor()
       : lock_(nullptr),
         condVar_(nullptr)
     { }
 
     ~Monitor() {
 #ifdef JS_THREADSAFE
@@ -75,33 +70,57 @@ class AutoLockMonitor
 #endif
 
     ~AutoLockMonitor() {
 #ifdef JS_THREADSAFE
         PR_Unlock(monitor.lock_);
 #endif
     }
 
-    void wait() {
+    bool isFor(Monitor &other) const {
+        return monitor.lock_ == other.lock_;
+    }
+
+    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
@@ -119,13 +138,17 @@ class AutoUnlockMonitor
     {}
 #endif
 
     ~AutoUnlockMonitor() {
 #ifdef JS_THREADSAFE
         PR_Lock(monitor.lock_);
 #endif
     }
+
+    bool isFor(Monitor &other) const {
+        return monitor.lock_ == other.lock_;
+    }
 };
 
 } // namespace js
 
 #endif /* vm_Monitor_h */
--- 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(*pool_));
     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.