Bug 1336326 (part 2) - Make sRegisteredThreadsMutex a StaticMutex. r=mstange.
authorNicholas Nethercote <nnethercote@mozilla.com>
Fri, 03 Feb 2017 13:11:34 +1100
changeset 340895 32550b42266999359049ab671fce22fdb5dc4f7b
parent 340894 dfcd7fa37af1a07dbe2d221735bcb192ad4c43e7
child 340896 65c5923d0feccdbe87b3dfc50a389e715d775a70
push id31318
push usercbook@mozilla.com
push dateMon, 06 Feb 2017 11:56:59 +0000
treeherdermozilla-central@1cc159c7a044 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1336326
milestone54.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 1336326 (part 2) - Make sRegisteredThreadsMutex a StaticMutex. r=mstange. StaticMutexes don't need to be created or destroyed, which avoids the need for checking if they still exist. This patch also adds locking to a few functions that lacked it. Every access to sRegisteredThreads is now protected appropriately.
tools/profiler/core/Sampler.cpp
tools/profiler/core/platform-linux.cc
tools/profiler/core/platform-macos.cc
tools/profiler/core/platform-win32.cc
tools/profiler/core/platform.cpp
tools/profiler/core/platform.h
--- a/tools/profiler/core/Sampler.cpp
+++ b/tools/profiler/core/Sampler.cpp
@@ -194,17 +194,17 @@ hasFeature(const char** aFeatures, uint3
   for(size_t i = 0; i < aFeatureCount; i++) {
     if (strcmp(aFeatures[i], aFeature) == 0)
       return true;
   }
   return false;
 }
 
 std::vector<ThreadInfo*>* Sampler::sRegisteredThreads = nullptr;
-mozilla::UniquePtr<mozilla::Mutex> Sampler::sRegisteredThreadsMutex;
+StaticMutex Sampler::sRegisteredThreadsMutex;
 
 Sampler::Sampler(double aInterval, int aEntrySize,
                  const char** aFeatures, uint32_t aFeatureCount,
                  const char** aThreadNameFilters, uint32_t aFilterCount)
   : interval_(aInterval)
   , paused_(false)
   , active_(false)
   , entrySize_(aEntrySize)
@@ -246,17 +246,17 @@ Sampler::Sampler(double aInterval, int a
   for (uint32_t i = 0; i < aFeatureCount; ++i) {
     mFeatures[i] = aFeatures[i];
   }
 
   bool ignore;
   sStartTime = mozilla::TimeStamp::ProcessCreation(ignore);
 
   {
-    MutexAutoLock lock(*sRegisteredThreadsMutex);
+    StaticMutexAutoLock lock(sRegisteredThreadsMutex);
 
     // Set up profiling for each registered thread, if appropriate
     for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
       ThreadInfo* info = sRegisteredThreads->at(i);
 
       RegisterThread(info);
     }
   }
@@ -274,17 +274,17 @@ Sampler::~Sampler()
 {
   MOZ_COUNT_DTOR(Sampler);
 
   if (IsActive())
     Stop();
 
   // Destroy ThreadInfo for all threads
   {
-    MutexAutoLock lock(*sRegisteredThreadsMutex);
+    StaticMutexAutoLock lock(sRegisteredThreadsMutex);
 
     for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
       ThreadInfo* info = sRegisteredThreads->at(i);
       // We've stopped profiling. We no longer need to retain
       // information for an old thread.
       if (info->IsPendingDelete()) {
         delete info;
         sRegisteredThreads->erase(sRegisteredThreads->begin() + i);
@@ -302,63 +302,63 @@ Sampler::~Sampler()
     mozilla::tasktracer::StopLogging();
   }
 #endif
 }
 
 void
 Sampler::Startup()
 {
+  StaticMutexAutoLock lock(sRegisteredThreadsMutex);
+
   sRegisteredThreads = new std::vector<ThreadInfo*>();
-  sRegisteredThreadsMutex = MakeUnique<Mutex>("sRegisteredThreadsMutex");
 
   // We could create the sLUL object and read unwind info into it at
   // this point.  That would match the lifetime implied by destruction
   // of it in Sampler::Shutdown just below.  However, that gives a big
   // delay on startup, even if no profiling is actually to be done.
   // So, instead, sLUL is created on demand at the first call to
   // Sampler::Start.
 }
 
 void
 Sampler::Shutdown()
 {
+  StaticMutexAutoLock lock(sRegisteredThreadsMutex);
+
   while (sRegisteredThreads->size() > 0) {
     delete sRegisteredThreads->back();
     sRegisteredThreads->pop_back();
   }
 
-  sRegisteredThreadsMutex = nullptr;
-  delete sRegisteredThreads;
-
   // UnregisterThread can be called after shutdown in XPCShell. Thus
   // we need to point to null to ignore such a call after shutdown.
-  sRegisteredThreadsMutex = nullptr;
+  delete sRegisteredThreads;
   sRegisteredThreads = nullptr;
 
 #if defined(USE_LUL_STACKWALK)
   // Delete the sLUL object, if it actually got created.
   if (sLUL) {
     delete sLUL;
     sLUL = nullptr;
   }
 #endif
 }
 
 bool
 Sampler::RegisterCurrentThread(const char* aName,
                                PseudoStack* aPseudoStack,
                                bool aIsMainThread, void* stackTop)
 {
-  if (!sRegisteredThreadsMutex) {
+  StaticMutexAutoLock lock(sRegisteredThreadsMutex);
+
+  if (!sRegisteredThreads) {
     return false;
   }
 
-  MutexAutoLock lock(*sRegisteredThreadsMutex);
-
   Thread::tid_t id = Thread::GetCurrentId();
 
   for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
     ThreadInfo* info = sRegisteredThreads->at(i);
     if (info->ThreadId() == id && !info->IsPendingDelete()) {
       // Thread already registered. This means the first unregister will be
       // too early.
       MOZ_ASSERT(false);
@@ -377,22 +377,22 @@ Sampler::RegisterCurrentThread(const cha
   sRegisteredThreads->push_back(info);
 
   return true;
 }
 
 void
 Sampler::UnregisterCurrentThread()
 {
-  if (!sRegisteredThreadsMutex) {
+  StaticMutexAutoLock lock(sRegisteredThreadsMutex);
+
+  if (!sRegisteredThreads) {
     return;
   }
 
-  MutexAutoLock lock(*sRegisteredThreadsMutex);
-
   Thread::tid_t id = Thread::GetCurrentId();
 
   for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
     ThreadInfo* info = sRegisteredThreads->at(i);
     if (info->ThreadId() == id && !info->IsPendingDelete()) {
       if (profiler_is_active()) {
         // We still want to show the results of this thread if you
         // save the profile shortly after a thread is terminated.
@@ -421,30 +421,35 @@ Sampler::StreamTaskTracer(SpliceableJSON
   aWriter.StartArrayProperty("data");
     UniquePtr<nsTArray<nsCString>> data = mozilla::tasktracer::GetLoggedData(sStartTime);
     for (uint32_t i = 0; i < data->Length(); ++i) {
       aWriter.StringElement((data->ElementAt(i)).get());
     }
   aWriter.EndArray();
 
   aWriter.StartArrayProperty("threads");
-    MutexAutoLock lock(*sRegisteredThreadsMutex);
+  {
+    StaticMutexAutoLock lock(sRegisteredThreadsMutex);
+
     for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
       // Thread meta data
       ThreadInfo* info = sRegisteredThreads->at(i);
       aWriter.StartObjectElement();
+      {
         if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
           // TODO Add the proper plugin name
           aWriter.StringProperty("name", "Plugin");
         } else {
           aWriter.StringProperty("name", info->Name());
         }
         aWriter.IntProperty("tid", static_cast<int>(info->ThreadId()));
+      }
       aWriter.EndObject();
     }
+  }
   aWriter.EndArray();
 
   aWriter.DoubleProperty("start", static_cast<double>(mozilla::tasktracer::GetStartTime()));
 #endif
 }
 
 
 void
@@ -660,17 +665,17 @@ Sampler::StreamJSON(SpliceableJSONWriter
     }
 
     // Lists the samples for each thread profile
     aWriter.StartArrayProperty("threads");
     {
       SetPaused(true);
 
       {
-        MutexAutoLock lock(*sRegisteredThreadsMutex);
+        StaticMutexAutoLock lock(sRegisteredThreadsMutex);
 
         for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
           // Thread not being profiled, skip it
           ThreadInfo* info = sRegisteredThreads->at(i);
           if (!info->hasProfile()) {
             continue;
           }
 
@@ -716,17 +721,17 @@ Sampler::StreamJSON(SpliceableJSONWriter
 }
 
 void
 Sampler::FlushOnJSShutdown(JSContext* aContext)
 {
   SetPaused(true);
 
   {
-    MutexAutoLock lock(*sRegisteredThreadsMutex);
+    StaticMutexAutoLock lock(sRegisteredThreadsMutex);
 
     for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
       // Thread not being profiled, skip it.
       ThreadInfo* info = sRegisteredThreads->at(i);
       if (!info->hasProfile() || info->IsPendingDelete()) {
         continue;
       }
 
--- a/tools/profiler/core/platform-linux.cc
+++ b/tools/profiler/core/platform-linux.cc
@@ -304,17 +304,17 @@ static void* SignalSender(void* arg) {
 
   TimeDuration lastSleepOverhead = 0;
   TimeStamp sampleStart = TimeStamp::Now();
   while (SamplerRegistry::sampler->IsActive()) {
 
     SamplerRegistry::sampler->DeleteExpiredMarkers();
 
     if (!SamplerRegistry::sampler->IsPaused()) {
-      MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
+      StaticMutexAutoLock lock(Sampler::sRegisteredThreadsMutex);
 
       bool isFirstProfiledThread = true;
       for (uint32_t i = 0; i < Sampler::sRegisteredThreads->size(); i++) {
         ThreadInfo* info = (*Sampler::sRegisteredThreads)[i];
 
         // This will be null if we're not interested in profiling this thread.
         if (!info->hasProfile() || info->IsPendingDelete()) {
           continue;
--- a/tools/profiler/core/platform-macos.cc
+++ b/tools/profiler/core/platform-macos.cc
@@ -170,18 +170,20 @@ public:
     mInstance = NULL;
   }
 
   void Run() {
     TimeDuration lastSleepOverhead = 0;
     TimeStamp sampleStart = TimeStamp::Now();
     while (SamplerRegistry::sampler->IsActive()) {
       SamplerRegistry::sampler->DeleteExpiredMarkers();
+
       if (!SamplerRegistry::sampler->IsPaused()) {
-        MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
+        StaticMutexAutoLock lock(Sampler::sRegisteredThreadsMutex);
+
         bool isFirstProfiledThread = true;
         for (uint32_t i = 0; i < Sampler::sRegisteredThreads->size(); i++) {
           ThreadInfo* info = (*Sampler::sRegisteredThreads)[i];
 
           // This will be null if we're not interested in profiling this thread.
           if (!info->hasProfile() || info->IsPendingDelete()) {
             continue;
           }
--- a/tools/profiler/core/platform-win32.cc
+++ b/tools/profiler/core/platform-win32.cc
@@ -161,17 +161,18 @@ class SamplerThread
     // adjust the resolution to match.
     if (mInterval < 10)
         ::timeBeginPeriod(mInterval);
 
     while (mSampler->IsActive()) {
       mSampler->DeleteExpiredMarkers();
 
       if (!mSampler->IsPaused()) {
-        mozilla::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
+        mozilla::StaticMutexAutoLock lock(Sampler::sRegisteredThreadsMutex);
+
         bool isFirstProfiledThread = true;
         for (uint32_t i = 0; i < Sampler::sRegisteredThreads->size(); i++) {
           ThreadInfo* info = (*Sampler::sRegisteredThreads)[i];
 
           // This will be null if we're not interested in profiling this thread.
           if (!info->hasProfile() || info->IsPendingDelete()) {
             continue;
           }
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -739,17 +739,17 @@ profiler_start(int aProfileEntries, doub
 
   gSampler =
     new Sampler(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL,
                 aProfileEntries ? aProfileEntries : PROFILE_DEFAULT_ENTRY,
                 aFeatures, aFeatureCount, aThreadNameFilters, aFilterCount);
 
   gSampler->Start();
   if (gSampler->ProfileJS() || gSampler->InPrivacyMode()) {
-    mozilla::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
+    mozilla::StaticMutexAutoLock lock(Sampler::sRegisteredThreadsMutex);
 
     for (uint32_t i = 0; i < Sampler::sRegisteredThreads->size(); i++) {
       ThreadInfo* info = (*Sampler::sRegisteredThreads)[i];
       if (info->IsPendingDelete() || !info->hasProfile()) {
         continue;
       }
       info->Stack()->reinitializeOnResume();
       if (gSampler->ProfileJS()) {
--- a/tools/profiler/core/platform.h
+++ b/tools/profiler/core/platform.h
@@ -37,17 +37,17 @@
 
 #ifdef XP_UNIX
 #include <pthread.h>
 #endif
 
 #include <stdint.h>
 #include <math.h>
 #include "MainThreadUtils.h"
-#include "mozilla/Mutex.h"
+#include "mozilla/StaticMutex.h"
 #include "ThreadResponsiveness.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Vector.h"
 #include "PlatformMacros.h"
 #include "v8-support.h"
 #include <vector>
@@ -301,17 +301,17 @@ public:
                                     PseudoStack* aPseudoStack,
                                     bool aIsMainThread, void* stackTop);
   static void UnregisterCurrentThread();
 
   static void Startup();
   // Should only be called on shutdown
   static void Shutdown();
 
-  static mozilla::UniquePtr<mozilla::Mutex> sRegisteredThreadsMutex;
+  static mozilla::StaticMutex sRegisteredThreadsMutex;
   static std::vector<ThreadInfo*>* sRegisteredThreads;
 
   static bool CanNotifyObservers() {
 #ifdef MOZ_WIDGET_GONK
     // We use profile.sh on b2g to manually select threads and options per process.
     return false;
 #elif defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
     // Android ANR reporter uses the profiler off the main thread