Bug 1340928 (part 2) - Don't use ThreadInfo to pass Linux memory measurements. r=mstange.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 15 Feb 2017 14:44:09 +1100
changeset 373441 a3a18d2124d73caac76f56fc87410fcaec7336b4
parent 373440 5b86ca9a7e8e3364e64fbab7c777f89305e0592e
child 373442 cbc8f0119f8ba08e5c2f9782107531c085e794d7
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1340928
milestone54.0a1
Bug 1340928 (part 2) - Don't use ThreadInfo to pass Linux memory measurements. r=mstange. This change means that all the relevant code is now within platform-linux-android.cpp, which is nice.
tools/profiler/core/ThreadInfo.cpp
tools/profiler/core/ThreadInfo.h
tools/profiler/core/platform-linux-android.cpp
--- a/tools/profiler/core/ThreadInfo.cpp
+++ b/tools/profiler/core/ThreadInfo.cpp
@@ -18,20 +18,16 @@ ThreadInfo::ThreadInfo(const char* aName
   : mName(strdup(aName))
   , mThreadId(aThreadId)
   , mIsMainThread(aIsMainThread)
   , mPseudoStack(aPseudoStack)
   , mPlatformData(AllocPlatformData(aThreadId))
   , mStackTop(aStackTop)
   , mPendingDelete(false)
   , mMutex(MakeUnique<mozilla::Mutex>("ThreadInfo::mMutex"))
-#if defined(GP_OS_linux) || defined(GP_OS_android)
-  , mRssMemory(0)
-  , mUssMemory(0)
-#endif
 {
   MOZ_COUNT_CTOR(ThreadInfo);
   mThread = NS_GetCurrentThread();
 
   // We don't have to guess on mac
 #if defined(GP_OS_darwin)
   pthread_t self = pthread_self();
   mStackTop = pthread_get_stackaddr_np(self);
--- a/tools/profiler/core/ThreadInfo.h
+++ b/tools/profiler/core/ThreadInfo.h
@@ -101,20 +101,11 @@ private:
   // FlushSamplesAndMarkers should be called to save them. These are spliced
   // into the final stream.
   mozilla::UniquePtr<char[]> mSavedStreamedSamples;
   mozilla::UniquePtr<char[]> mSavedStreamedMarkers;
   mozilla::Maybe<UniqueStacks> mUniqueStacks;
 
   mozilla::UniquePtr<mozilla::Mutex> mMutex;
   ThreadResponsiveness mRespInfo;
-
-#if defined(GP_OS_linux) || defined(GP_OS_android)
-  // Only Linux is using a signal sender, instead of stopping the thread, so we
-  // need some space to store the data which cannot be collected in the signal
-  // handler code.
-public:
-  int64_t mRssMemory;
-  int64_t mUssMemory;
-#endif
 };
 
 #endif
--- a/tools/profiler/core/platform-linux-android.cpp
+++ b/tools/profiler/core/platform-linux-android.cpp
@@ -140,17 +140,23 @@ static void paf_parent(void) {
 
 // Set up the fork handlers.
 static void* setup_atfork() {
   pthread_atfork(paf_prepare, paf_parent, NULL);
   return NULL;
 }
 #endif /* !defined(GP_OS_android) */
 
+// Global variables through which data is sent from SigprofSender() to
+// SigprofHandler(). gSignalHandlingDone provides inter-thread synchronization.
 static ThreadInfo* gCurrentThreadInfo;
+static int64_t gRssMemory;
+static int64_t gUssMemory;
+
+// Semaphore used to coordinate SigprofSender() and SigprofHandler().
 static sem_t gSignalHandlingDone;
 
 static void SetSampleContext(TickSample* sample, void* context)
 {
   // Extracting the sample from the context is extremely machine dependent.
   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
   mcontext_t& mcontext = ucontext->uc_mcontext;
 #if defined(GP_ARCH_x86)
@@ -180,18 +186,18 @@ SigprofHandler(int signal, siginfo_t* in
   TickSample sample_obj;
   TickSample* sample = &sample_obj;
   sample->context = context;
 
   // Extract the current pc and sp.
   SetSampleContext(sample, context);
   sample->threadInfo = gCurrentThreadInfo;
   sample->timestamp = mozilla::TimeStamp::Now();
-  sample->rssMemory = sample->threadInfo->mRssMemory;
-  sample->ussMemory = sample->threadInfo->mUssMemory;
+  sample->rssMemory = gRssMemory;
+  sample->ussMemory = gUssMemory;
 
   Tick(sample);
 
   sem_post(&gSignalHandlingDone);
   errno = savedErrno;
 }
 
 #if defined(GP_OS_android)
@@ -293,21 +299,21 @@ SigprofSender(void* aArg)
 
         int threadId = info->ThreadId();
         MOZ_ASSERT(threadId != my_tid);
 
         // Profile from the signal sender for information which is not signal
         // safe, and will have low variation between the emission of the signal
         // and the signal handler catch.
         if (isFirstProfiledThread && gProfileMemory) {
-          info->mRssMemory = nsMemoryReporterManager::ResidentFast();
-          info->mUssMemory = nsMemoryReporterManager::ResidentUnique();
+          gRssMemory = nsMemoryReporterManager::ResidentFast();
+          gUssMemory = nsMemoryReporterManager::ResidentUnique();
         } else {
-          info->mRssMemory = 0;
-          info->mUssMemory = 0;
+          gRssMemory = 0;
+          gUssMemory = 0;
         }
 
         // Profile from the signal handler for information which is signal safe
         // and needs to be precise too, such as the stack of the interrupted
         // thread.
         if (tgkill(vm_tgid_, threadId, SIGPROF) != 0) {
           printf_stderr("profiler failed to signal tid=%d\n", threadId);
 #ifdef DEBUG
@@ -316,16 +322,19 @@ SigprofSender(void* aArg)
           continue;
 #endif
         }
 
         // Wait for the signal handler to run before moving on to the next one.
         sem_wait(&gSignalHandlingDone);
 
         gCurrentThreadInfo = nullptr;
+        gRssMemory = 0;
+        gUssMemory = 0;
+
         isFirstProfiledThread = false;
       }
 #if defined(USE_LUL_STACKWALK)
       // The LUL unwind object accumulates frame statistics. Periodically we
       // should poke it to give it a chance to print those statistics. This
       // involves doing I/O (fprintf, __android_log_print, etc.) and so can't
       // safely be done from the unwinder threads, which is why it is done
       // here.
@@ -360,16 +369,18 @@ PlatformStart()
   // called only from the main thread, so this is OK in general.
   if (!gLUL) {
      gLUL_initialization_routine();
   }
 #endif
 
   // Initialize signal handler communication
   gCurrentThreadInfo = nullptr;
+  gRssMemory = 0;
+  gUssMemory = 0;
   if (sem_init(&gSignalHandlingDone, /* pshared: */ 0, /* value: */ 0) != 0) {
     LOG("Error initializing semaphore");
     return;
   }
 
   // Request profiling signals.
   LOG("Request signal");
   struct sigaction sa;