Bug 981132 - set up atfork on the main thread. r=bgirard
authorViktor Stanchev <vstanchev@mozilla.com>
Wed, 12 Mar 2014 16:32:40 -0400
changeset 190636 4853e04fe2a63354cc0edc9979b09c132b0904be
parent 190635 57da41536eb408330d677328f726b10d67e11691
child 190637 d736ff28e9dc97ea92d88954a042facc6f733fc4
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgirard
bugs981132
milestone30.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 981132 - set up atfork on the main thread. r=bgirard
tools/profiler/platform-linux.cc
tools/profiler/platform-macos.cc
tools/profiler/platform-win32.cc
tools/profiler/platform.cpp
tools/profiler/platform.h
--- a/tools/profiler/platform-linux.cc
+++ b/tools/profiler/platform-linux.cc
@@ -130,18 +130,17 @@ static void paf_prepare(void) {
 
 // In the parent, just after the fork, return pausedness to the
 // pre-fork state.
 static void paf_parent(void) {
   if (Sampler::GetActiveSampler())
     Sampler::GetActiveSampler()->SetPaused(was_paused);
 }
 
-// Set up the fork handlers.  This is called just once, at the first
-// call to SenderEntry.
+// Set up the fork handlers.
 static void* setup_atfork() {
   pthread_atfork(paf_prepare, paf_parent, NULL);
   return NULL;
 }
 #endif /* !defined(ANDROID) */
 
 struct SamplerRegistry {
   static void AddActiveSampler(Sampler *sampler) {
@@ -257,24 +256,16 @@ Sampler::AllocPlatformData(int aThreadId
 Sampler::FreePlatformData(PlatformData* aData)
 {
   delete aData;
 }
 
 static void* SignalSender(void* arg) {
   // Taken from platform_thread_posix.cc
   prctl(PR_SET_NAME, "SamplerThread", 0, 0, 0);
-# if defined(ANDROID)
-  // pthread_atfork isn't available on Android.
-  void* initialize_atfork = NULL;
-# else
-  // This call is done just once, at the first call to SenderEntry.
-  // It returns NULL.
-  static void* initialize_atfork = setup_atfork();
-# endif
 
 #ifdef MOZ_NUWA_PROCESS
   // If the Nuwa process is enabled, we need to mark and freeze the sampler
   // thread in the Nuwa process and have this thread recreated in the spawned
   // child.
   if(IsNuwaProcess()) {
     NuwaMarkCurrentThread(nullptr, nullptr);
     // Freeze the thread here so the spawned child will get the correct tgid
@@ -323,17 +314,17 @@ static void* SignalSender(void* arg) {
     // occuring during signal delivery.
     // TODO measure and confirm this.
     int interval = floor(SamplerRegistry::sampler->interval() * 1000 + 0.5) - 100;
     if (interval <= 0) {
       interval = 1;
     }
     OS::SleepMicro(interval);
   }
-  return initialize_atfork; // which is guaranteed to be NULL
+  return 0;
 }
 
 Sampler::Sampler(double interval, bool profiling, int entrySize)
     : interval_(interval),
       profiling_(profiling),
       paused_(false),
       active_(false),
       entrySize_(entrySize) {
@@ -560,29 +551,39 @@ static void StartSignalHandler(int signa
   profiler_start(PROFILE_DEFAULT_ENTRY, 1,
       features, featureCount,
       threadNames, threadCount);
 
   freeArray(threadNames, threadCount);
   freeArray(features, featureCount);
 }
 
-void OS::RegisterStartHandler()
+void OS::Startup()
 {
   LOG("Registering start signal");
   struct sigaction sa;
   sa.sa_sigaction = StartSignalHandler;
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = SA_RESTART | SA_SIGINFO;
   if (sigaction(SIGSTART, &sa, &old_sigstart_signal_handler) != 0) {
     LOG("Error installing signal");
   }
 }
+
+#else
+
+void OS::Startup() {
+  // Set up the fork handlers.
+  setup_atfork();
+}
+
 #endif
 
+
+
 void TickSample::PopulateContext(void* aContext)
 {
   MOZ_ASSERT(aContext);
   ucontext_t* pContext = reinterpret_cast<ucontext_t*>(aContext);
   if (!getcontext(pContext)) {
     context = pContext;
     SetSampleContext(this, aContext);
   }
--- a/tools/profiler/platform-macos.cc
+++ b/tools/profiler/platform-macos.cc
@@ -51,16 +51,19 @@ struct SamplerRegistry {
 };
 
 Sampler *SamplerRegistry::sampler = NULL;
 
 // 0 is never a valid thread id on MacOSX since a ptread_t is
 // a pointer.
 static const pthread_t kNoThread = (pthread_t) 0;
 
+void OS::Startup() {
+}
+
 void OS::Sleep(int milliseconds) {
   usleep(1000 * milliseconds);
 }
 
 void OS::SleepMicro(int microseconds) {
   usleep(microseconds);
 }
 
--- a/tools/profiler/platform-win32.cc
+++ b/tools/profiler/platform-win32.cc
@@ -263,16 +263,19 @@ void Thread::Join() {
 }
 
 /* static */ Thread::tid_t
 Thread::GetCurrentId()
 {
   return GetCurrentThreadId();
 }
 
+void OS::Startup() {
+}
+
 void OS::Sleep(int milliseconds) {
   ::Sleep(milliseconds);
 }
 
 bool Sampler::RegisterCurrentThread(const char* aName,
                                     PseudoStack* aPseudoStack,
                                     bool aIsMainThread, void* stackTop)
 {
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/platform.cpp
@@ -473,18 +473,18 @@ void mozilla_sampler_init(void* stackTop
                                    gGeckoThreadName : "Application Thread",
                                  stack, isMainThread, stackTop);
 
   // Read mode settings from MOZ_PROFILER_MODE and interval
   // settings from MOZ_PROFILER_INTERVAL and stack-scan threshhold
   // from MOZ_PROFILER_STACK_SCAN.
   read_profiler_env_vars();
 
-  // Allow the profiler to be started using signals
-  OS::RegisterStartHandler();
+  // platform specific initialization
+  OS::Startup();
 
   // Initialize I/O interposing
   mozilla::IOInterposer::Init();
   // Initialize NSPR I/O Interposing
   mozilla::InitNSPRIOInterposing();
 
   // We can't open pref so we use an environment variable
   // to know if we should trigger the profiler on startup
--- a/tools/profiler/platform.h
+++ b/tools/profiler/platform.h
@@ -119,23 +119,18 @@ class OS {
  public:
 
   // Sleep for a number of milliseconds.
   static void Sleep(const int milliseconds);
 
   // Sleep for a number of microseconds.
   static void SleepMicro(const int microseconds);
 
-  // On supported platforms, setup a signal handler which would start
-  // the profiler.
-#if defined(ANDROID)
-  static void RegisterStartHandler();
-#else
-  static void RegisterStartHandler() {}
-#endif
+  // Called on startup to initialize platform specific things
+  static void Startup();
 
  private:
   static const int msPerSecond = 1000;
 
 };