bug 1072780: patch 3 - Fix up Revive() to not trigger assertions, and also to avoid Init() (blocking) on MainThread r=roc
authorRandell Jesup <rjesup@jesup.org>
Sun, 28 Sep 2014 12:07:24 -0400
changeset 207590 34c741cf2e57ca6246ad9b51d9d4579aab368373
parent 207589 509e62e4bc1afd68c7813cb7077b147c1a96d32a
child 207591 765e4c810ce0a49b7a79766c8a13162128d17fba
push id49728
push userrjesup@wgate.com
push dateSun, 28 Sep 2014 23:58:36 +0000
treeherdermozilla-inbound@765e4c810ce0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1072780
milestone35.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 1072780: patch 3 - Fix up Revive() to not trigger assertions, and also to avoid Init() (blocking) on MainThread r=roc
content/media/GraphDriver.cpp
content/media/MediaStreamGraphImpl.h
--- a/content/media/GraphDriver.cpp
+++ b/content/media/GraphDriver.cpp
@@ -220,31 +220,38 @@ private:
   ThreadedDriver* mDriver;
 };
 
 void
 ThreadedDriver::Start()
 {
   LIFECYCLE_LOG("Starting thread for a SystemClockDriver  %p\n", mGraphImpl);
   nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
-  NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
+  // Note: mThread may be null during event->Run() if we pass to NewNamedThread!  See AudioInitTask
+  nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread));
+  if (NS_SUCCEEDED(rv)) {
+    mThread->Dispatch(event, NS_DISPATCH_NORMAL);
+  }
 }
 
 void
 ThreadedDriver::Resume()
 {
   Start();
 }
 
 void
 ThreadedDriver::Revive()
 {
+  // Note: only called on MainThread, without monitor
+  // We know were weren't in a running state
   STREAM_LOG(PR_LOG_DEBUG, ("AudioCallbackDriver reviving."));
   // If we were switching, switch now. Otherwise, tell thread to run the main
   // loop again.
+  MonitorAutoLock mon(mGraphImpl->GetMonitor());
   if (mNextDriver) {
     mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd,
                                mStateComputedTime, mNextStateComputedTime);
     mGraphImpl->SetCurrentDriver(mNextDriver);
     mNextDriver->Start();
   } else {
     nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
     mThread->Dispatch(event, NS_DISPATCH_NORMAL);
@@ -662,26 +669,31 @@ AudioCallbackDriver::Stop()
   if (cubeb_stream_stop(mAudioStream) != CUBEB_OK) {
     NS_WARNING("Could not stop cubeb stream for MSG.");
   }
 }
 
 void
 AudioCallbackDriver::Revive()
 {
+  // Note: only called on MainThread, without monitor
+  // We know were weren't in a running state
   STREAM_LOG(PR_LOG_DEBUG, ("AudioCallbackDriver reviving."));
   // If we were switching, switch now. Otherwise, start the audio thread again.
+  MonitorAutoLock mon(mGraphImpl->GetMonitor());
   if (mNextDriver) {
     mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd,
-                               mStateComputedTime, mNextStateComputedTime);
+                              mStateComputedTime, mNextStateComputedTime);
     mGraphImpl->SetCurrentDriver(mNextDriver);
     mNextDriver->Start();
   } else {
-    Init();
-    Start();
+    STREAM_LOG(PR_LOG_DEBUG, ("Starting audio threads for MediaStreamGraph %p from a new thread.", mGraphImpl));
+    nsRefPtr<AsyncCubebTask> initEvent =
+      new AsyncCubebTask(this, AsyncCubebTask::INIT);
+    initEvent->Dispatch();
   }
 }
 
 void
 AudioCallbackDriver::GetIntervalForIteration(GraphTime& aFrom,
                                              GraphTime& aTo)
 {
 }
--- a/content/media/MediaStreamGraphImpl.h
+++ b/content/media/MediaStreamGraphImpl.h
@@ -433,19 +433,26 @@ public:
     return mDriver;
   }
 
   /**
    * Effectively set the new driver, while we are switching.
    * It is only safe to call this at the very end of an iteration, when there
    * has been a SwitchAtNextIteration call during the iteration. The driver
    * should return and pass the control to the new driver shortly after.
+   * We can also switch from Revive() (on MainThread), in which case the
+   * monitor is held
    */
   void SetCurrentDriver(GraphDriver* aDriver) {
-    MOZ_ASSERT(mDriver->OnThread());
+#ifdef DEBUG
+    // #ifdef since we're not wrapping it all in MOZ_ASSERT()
+    if (!mDriver->OnThread()) {
+      mMonitor.AssertCurrentThreadOwns();
+    }
+#endif
     mDriver = aDriver;
   }
 
   Monitor& GetMonitor() {
     return mMonitor;
   }
 
   /**