Bug 1330184 - Register/unregister the IOInterposeObserver on the main thread, regardless of what thread the profiler is started / stopped on. r=njn
authorMarkus Stange <mstange@themasta.com>
Tue, 16 May 2017 17:35:05 -0400
changeset 409558 15728eea17988c229b64b5d14df6e8eb15cd529e
parent 409557 4f297a3633aab8741d989a190cf32d7309582c53
child 409559 640a7914237719f196d8286410efa18bea33902e
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1330184
milestone55.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 1330184 - Register/unregister the IOInterposeObserver on the main thread, regardless of what thread the profiler is started / stopped on. r=njn MozReview-Commit-ID: 8Y0rspxBJw3
tools/profiler/core/platform.cpp
tools/profiler/gecko/ProfilerIOInterposeObserver.h
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -292,26 +292,42 @@ private:
   {
     // Deep copy aFilters.
     MOZ_ALWAYS_TRUE(mFilters.resize(aFilterCount));
     for (uint32_t i = 0; i < aFilterCount; ++i) {
       mFilters[i] = aFilters[i];
     }
 
     if (mInterposeObserver) {
-      mozilla::IOInterposer::Register(mozilla::IOInterposeObserver::OpAll,
-                                      mInterposeObserver.get());
+      // We need to register the observer on the main thread, because we want
+      // to observe IO that happens on the main thread.
+      if (NS_IsMainThread()) {
+        IOInterposer::Register(IOInterposeObserver::OpAll, mInterposeObserver);
+      } else {
+        RefPtr<ProfilerIOInterposeObserver> observer = mInterposeObserver;
+        NS_DispatchToMainThread(NS_NewRunnableFunction([=]() {
+          IOInterposer::Register(IOInterposeObserver::OpAll, observer);
+        }));
+      }
     }
   }
 
   ~ActivePS()
   {
     if (mInterposeObserver) {
-      mozilla::IOInterposer::Unregister(mozilla::IOInterposeObserver::OpAll,
-                                        mInterposeObserver.get());
+      // We need to unregister the observer on the main thread, because that's
+      // where we've registered it.
+      if (NS_IsMainThread()) {
+        IOInterposer::Unregister(IOInterposeObserver::OpAll, mInterposeObserver);
+      } else {
+        RefPtr<ProfilerIOInterposeObserver> observer = mInterposeObserver;
+        NS_DispatchToMainThread(NS_NewRunnableFunction([=]() {
+          IOInterposer::Unregister(IOInterposeObserver::OpAll, observer);
+        }));
+      }
     }
   }
 
   bool ThreadSelected(const char* aThreadName)
   {
     // This function runs both on and off the main thread.
 
     MOZ_RELEASE_ASSERT(sInstance);
@@ -444,17 +460,17 @@ private:
   const UniquePtr<ProfileBuffer> mBuffer;
 
   // The current sampler thread. This class is not responsible for destroying
   // the SamplerThread object; the Destroy() method returns it so the caller
   // can destroy it.
   SamplerThread* const mSamplerThread;
 
   // The interposer that records main thread I/O.
-  const UniquePtr<mozilla::ProfilerIOInterposeObserver> mInterposeObserver;
+  const RefPtr<mozilla::ProfilerIOInterposeObserver> mInterposeObserver;
 
   // Is the profiler paused?
   bool mIsPaused;
 
 #if defined(GP_OS_linux)
   // Used to record whether the profiler was paused just before forking. False
   // at all times except just before/after forking.
   bool mWasPaused;
--- a/tools/profiler/gecko/ProfilerIOInterposeObserver.h
+++ b/tools/profiler/gecko/ProfilerIOInterposeObserver.h
@@ -3,26 +3,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef PROFILERIOINTERPOSEOBSERVER_H
 #define PROFILERIOINTERPOSEOBSERVER_H
 
 #ifdef MOZ_GECKO_PROFILER
 
 #include "mozilla/IOInterposer.h"
+#include "nsISupportsImpl.h"
 
 namespace mozilla {
 
 /**
  * This class is the observer that calls into the profiler whenever
  * main thread I/O occurs.
  */
 class ProfilerIOInterposeObserver final : public IOInterposeObserver
 {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProfilerIOInterposeObserver)
+
 public:
   virtual void Observe(Observation& aObservation);
+
+protected:
+  virtual ~ProfilerIOInterposeObserver() {}
 };
 
 } // namespace mozilla
 
 #endif // MOZ_GECKO_PROFILER
 
 #endif // PROFILERIOINTERPOSEOBSERVER_H