Bug 1091037 - Raise ImageBridge thread priority r=gsvelto,nical
authorSotaro Ikeda <sikeda@mozilla.com>
Thu, 07 May 2015 06:53:47 -0700
changeset 272623 d0b48a557161308bc7459afe0f7ce5fbcd8e51c5
parent 272622 ce6cfd9bad2fd2970b6470e22e68f5a6ac44f895
child 272624 ee863cf58138c1d0c5eecd19334ecf68fa1f5ad2
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgsvelto, nical
bugs1091037
milestone40.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 1091037 - Raise ImageBridge thread priority r=gsvelto,nical
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/ImageBridgeParent.cpp
gfx/layers/ipc/ImageBridgeParent.h
gfx/layers/ipc/PImageBridge.ipdl
hal/Hal.cpp
hal/Hal.h
hal/fallback/FallbackThreadPriority.cpp
hal/gonk/GonkHal.cpp
hal/sandbox/SandboxHal.cpp
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -521,16 +521,29 @@ ImageBridgeChild::EndTransaction()
     }
     default:
       NS_RUNTIMEABORT("not reached");
     }
   }
   SendPendingAsyncMessges();
 }
 
+void
+ImageBridgeChild::SendImageBridgeThreadId()
+{
+#ifdef MOZ_WIDGET_GONK
+  SendImageBridgeThreadId(gettid());
+#endif
+}
+
+static void CallSendImageBridgeThreadId(ImageBridgeChild* aImageBridgeChild)
+{
+  MOZ_ASSERT(InImageBridgeChildThread());
+  aImageBridgeChild->SendImageBridgeThreadId();
+}
 
 PImageBridgeChild*
 ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
                                         ProcessId aOtherPid)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   gfxPlatform::GetPlatform();
@@ -540,16 +553,20 @@ ImageBridgeChild::StartUpInChildProcess(
     return nullptr;
   }
 
   sImageBridgeChildSingleton = new ImageBridgeChild();
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction(ConnectImageBridgeInChildProcess,
                         aTransport, aOtherPid));
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    FROM_HERE,
+    NewRunnableFunction(CallSendImageBridgeThreadId,
+                        sImageBridgeChildSingleton.get()));
 
   return sImageBridgeChildSingleton;
 }
 
 void ImageBridgeChild::ShutDown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (ImageBridgeChild::IsCreated()) {
@@ -593,16 +610,20 @@ bool ImageBridgeChild::StartUpOnThread(T
     sImageBridgeChildThread = aThread;
     if (!aThread->IsRunning()) {
       aThread->Start();
     }
     sImageBridgeChildSingleton = new ImageBridgeChild();
     sImageBridgeParentSingleton = new ImageBridgeParent(
       CompositorParent::CompositorLoop(), nullptr, base::GetCurrentProcId());
     sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
+    sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+      FROM_HERE,
+      NewRunnableFunction(CallSendImageBridgeThreadId,
+                          sImageBridgeChildSingleton.get()));
     return true;
   } else {
     return false;
   }
 }
 
 bool InImageBridgeChildThread()
 {
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -147,16 +147,19 @@ public:
   static ImageBridgeChild* GetSingleton();
 
 
   /**
    * Dispatches a task to the ImageBridgeChild thread to do the connection
    */
   void ConnectAsync(ImageBridgeParent* aParent);
 
+  using PImageBridgeChild::SendImageBridgeThreadId;
+  void SendImageBridgeThreadId();
+
   static void IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier);
 
   void BeginTransaction();
   void EndTransaction();
 
   /**
    * Returns the ImageBridgeChild's thread.
    *
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -7,16 +7,18 @@
 #include "ImageBridgeParent.h"
 #include <stdint.h>                     // for uint64_t, uint32_t
 #include "CompositableHost.h"           // for CompositableParent, Create
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/process.h"               // for ProcessId
 #include "base/task.h"                  // for CancelableTask, DeleteTask, etc
 #include "base/tracked.h"               // for FROM_HERE
 #include "mozilla/gfx/Point.h"                   // for IntSize
+#include "mozilla/Hal.h"                // for hal::SetCurrentThreadPriority()
+#include "mozilla/HalTypes.h"           // for hal::THREAD_PRIORITY_COMPOSITOR
 #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/ipc/Transport.h"      // for Transport
 #include "mozilla/layers/CompositableTransactionParent.h"
 #include "mozilla/layers/CompositorParent.h"  // for CompositorParent
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/LayersMessages.h"  // for EditReply
 #include "mozilla/layers/LayersSurfaces.h"  // for PGrallocBufferParent
@@ -48,16 +50,17 @@ MessageLoop* ImageBridgeParent::sMainLoo
 // defined in CompositorParent.cpp
 CompositorThreadHolder* GetCompositorThreadHolder();
 
 ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
                                      Transport* aTransport,
                                      ProcessId aChildProcessId)
   : mMessageLoop(aLoop)
   , mTransport(aTransport)
+  , mSetChildThreadPriority(false)
   , mCompositorThreadHolder(GetCompositorThreadHolder())
 {
   MOZ_ASSERT(NS_IsMainThread());
   sMainLoop = MessageLoop::current();
 
   // top-level actors must be destroyed on the main thread.
   SetMessageLoopToPostDestructionTo(sMainLoop);
 
@@ -90,16 +93,30 @@ ImageBridgeParent::GetCompositorBackendT
 void
 ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   MessageLoop::current()->PostTask(
     FROM_HERE,
     NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy));
 }
 
+bool
+ImageBridgeParent::RecvImageBridgeThreadId(const PlatformThreadId& aThreadId)
+{
+  MOZ_ASSERT(!mSetChildThreadPriority);
+  if (mSetChildThreadPriority) {
+    return false;
+  }
+  mSetChildThreadPriority = true;
+#ifdef MOZ_WIDGET_GONK
+  hal::SetThreadPriority(aThreadId, hal::THREAD_PRIORITY_COMPOSITOR);
+#endif
+  return true;
+}
+
 class MOZ_STACK_CLASS AutoImageBridgeParentAsyncMessageSender
 {
 public:
   explicit AutoImageBridgeParentAsyncMessageSender(ImageBridgeParent* aImageBridge)
     : mImageBridge(aImageBridge) {}
 
   ~AutoImageBridgeParentAsyncMessageSender()
   {
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -62,16 +62,17 @@ public:
   virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
 
   virtual base::ProcessId GetChildProcessId() override
   {
     return OtherPid();
   }
 
   // PImageBridge
+  virtual bool RecvImageBridgeThreadId(const PlatformThreadId& aThreadId) override;
   virtual bool RecvUpdate(EditArray&& aEdits, EditReplyArray* aReply) override;
   virtual bool RecvUpdateNoSwap(EditArray&& aEdits) override;
 
   virtual bool IsAsync() const override { return true; }
 
   PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
                                                 uint64_t*) override;
   bool DeallocPCompositableParent(PCompositableParent* aActor) override;
@@ -138,23 +139,24 @@ public:
   // Overriden from IToplevelProtocol
   IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
                 base::ProcessHandle aPeerProcess,
                 mozilla::ipc::ProtocolCloneContext* aCtx) override;
 
 private:
   void DeferredDestroy();
-
   MessageLoop* mMessageLoop;
   Transport* mTransport;
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   nsRefPtr<ImageBridgeParent> mSelfRef;
 
+  bool mSetChildThreadPriority;
+
   /**
    * Map of all living ImageBridgeParent instances
    */
   static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges;
 
   static MessageLoop* sMainLoop;
 
   nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -10,16 +10,18 @@ include protocol PLayer;
 include protocol PTexture;
 include ProtocolTypes;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
 
+using PlatformThreadId from "base/platform_thread.h";
+
 namespace mozilla {
 namespace layers {
 
 /**
  * The PImageBridge protocol is used to allow isolated threads or processes to push
  * frames directly to the compositor thread/process without relying on the main thread
  * which might be too busy dealing with content script.
  */
@@ -28,16 +30,18 @@ sync protocol PImageBridge
   manages PCompositable;
   manages PTexture;
 
 child:
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
 parent:
 
+  async ImageBridgeThreadId(PlatformThreadId aTreahdId);
+
   sync Update(CompositableOperation[] ops) returns (EditReply[] reply);
   async UpdateNoSwap(CompositableOperation[] ops);
 
   // First step of the destruction sequence. This puts ImageBridge
   // in a state in which it can't send asynchronous messages
   // so as to not race with the upcomming Stop message and destruction.
   // In the child side, the Stop message is not sent right after WillStop,
   // it is scheduled in the ImageBridgeChild's message queue in order to ensure
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -859,16 +859,23 @@ SetProcessPriority(int aPid, ProcessPrio
 }
 
 void
 SetCurrentThreadPriority(hal::ThreadPriority aThreadPriority)
 {
   PROXY_IF_SANDBOXED(SetCurrentThreadPriority(aThreadPriority));
 }
 
+void
+SetThreadPriority(PlatformThreadId aThreadId,
+                  hal::ThreadPriority aThreadPriority)
+{
+  PROXY_IF_SANDBOXED(SetThreadPriority(aThreadId, aThreadPriority));
+}
+
 // From HalTypes.h.
 const char*
 ProcessPriorityToString(ProcessPriority aPriority)
 {
   switch (aPriority) {
   case PROCESS_PRIORITY_MASTER:
     return "MASTER";
   case PROCESS_PRIORITY_PREALLOC:
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_Hal_h
 #define mozilla_Hal_h
 
 #include "mozilla/hal_sandbox/PHal.h"
 #include "mozilla/HalTypes.h"
 #include "base/basictypes.h"
+#include "base/platform_thread.h"
 #include "mozilla/Observer.h"
 #include "mozilla/Types.h"
 #include "nsTArray.h"
 #include "mozilla/dom/MozPowerManagerBinding.h"
 #include "mozilla/dom/battery/Types.h"
 #include "mozilla/dom/network/Types.h"
 #include "mozilla/dom/power/Types.h"
 #include "mozilla/dom/ScreenOrientation.h"
@@ -481,16 +482,24 @@ void SetProcessPriority(int aPid,
 /**
  * Set the current thread's priority to appropriate platform-specific value for
  * given functionality. Instead of providing arbitrary priority numbers you
  * must specify a type of function like THREAD_PRIORITY_COMPOSITOR.
  */
 void SetCurrentThreadPriority(hal::ThreadPriority aThreadPriority);
 
 /**
+ * Set a thread priority to appropriate platform-specific value for
+ * given functionality. Instead of providing arbitrary priority numbers you
+ * must specify a type of function like THREAD_PRIORITY_COMPOSITOR.
+ */
+void SetThreadPriority(PlatformThreadId aThreadId,
+                       hal::ThreadPriority aThreadPriority);
+
+/**
  * Register an observer for the FM radio.
  */
 void RegisterFMRadioObserver(hal::FMRadioObserver* aRadioObserver);
 
 /**
  * Unregister the observer for the FM radio.
  */
 void UnregisterFMRadioObserver(hal::FMRadioObserver* aRadioObserver);
--- a/hal/fallback/FallbackThreadPriority.cpp
+++ b/hal/fallback/FallbackThreadPriority.cpp
@@ -12,10 +12,18 @@ namespace hal_impl {
 
 void
 SetCurrentThreadPriority(ThreadPriority aPriority)
 {
   HAL_LOG("FallbackThreadPriority - SetCurrentThreadPriority(%d)\n",
           ThreadPriorityToString(aPriority));
 }
 
+void
+SetThreadPriority(PlatformThreadId aThreadId,
+                  ThreadPriority aPriority)
+{
+  HAL_LOG("FallbackThreadPriority - SetThreadPriority(%d, %d)\n",
+          aThreadId, ThreadPriorityToString(aPriority));
+}
+
 } // hal_impl
 } // namespace mozilla
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -1909,17 +1909,17 @@ EnsureThreadPriorityPrefs(ThreadPriority
     Preferences::AddIntVarCache(&prefs->priorities[i].realTime,
                                 realTimeStr.get());
   }
 
   prefs->initialized = true;
 }
 
 static void
-SetThreadPriority(pid_t aTid, hal::ThreadPriority aThreadPriority)
+DoSetThreadPriority(pid_t aTid, hal::ThreadPriority aThreadPriority)
 {
   // See bug 999115, we can only read preferences on the main thread otherwise
   // we create a race condition in HAL
   MOZ_ASSERT(NS_IsMainThread(), "Can only set thread priorities on main thread");
   MOZ_ASSERT(aThreadPriority >= 0);
 
   static ThreadPriorityPrefs prefs = { 0 };
   EnsureThreadPriorityPrefs(&prefs);
@@ -1960,35 +1960,42 @@ public:
   SetThreadPriorityRunnable(pid_t aThreadId, hal::ThreadPriority aThreadPriority)
     : mThreadId(aThreadId)
     , mThreadPriority(aThreadPriority)
   { }
 
   NS_IMETHOD Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Can only set thread priorities on main thread");
-    hal_impl::SetThreadPriority(mThreadId, mThreadPriority);
+    hal_impl::DoSetThreadPriority(mThreadId, mThreadPriority);
     return NS_OK;
   }
 
 private:
   pid_t mThreadId;
   hal::ThreadPriority mThreadPriority;
 };
 
 } // anonymous namespace
 
 void
 SetCurrentThreadPriority(ThreadPriority aThreadPriority)
 {
+  pid_t threadId = gettid();
+  hal_impl::SetThreadPriority(threadId, aThreadPriority);
+}
+
+void
+SetThreadPriority(PlatformThreadId aThreadId,
+                         ThreadPriority aThreadPriority)
+{
   switch (aThreadPriority) {
     case THREAD_PRIORITY_COMPOSITOR: {
-      pid_t threadId = gettid();
       nsCOMPtr<nsIRunnable> runnable =
-        new SetThreadPriorityRunnable(threadId, aThreadPriority);
+        new SetThreadPriorityRunnable(aThreadId, aThreadPriority);
       NS_DispatchToMainThread(runnable);
       break;
     }
     default:
       HAL_LOG("Unrecognized thread priority %d; Doing nothing",
               aThreadPriority);
       return;
   }
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -351,16 +351,23 @@ void
 SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
 {
   NS_RUNTIMEABORT("Only the main process may set processes' priorities.");
 }
 
 void
 SetCurrentThreadPriority(ThreadPriority aThreadPriority)
 {
+  NS_RUNTIMEABORT("Setting current thread priority cannot be called from sandboxed contexts.");
+}
+
+void
+SetThreadPriority(PlatformThreadId aThreadId,
+                  ThreadPriority aThreadPriority)
+{
   NS_RUNTIMEABORT("Setting thread priority cannot be called from sandboxed contexts.");
 }
 
 void
 EnableFMRadio(const hal::FMRadioSettings& aSettings)
 {
   NS_RUNTIMEABORT("FM radio cannot be called from sandboxed contexts.");
 }