[compiler-rt] r177246 - [Sanitizer] Get rid of global mutexes in StopTheWorld implementation

Alexey Samsonov samsonov at google.com
Sun Mar 17 23:27:14 PDT 2013


Author: samsonov
Date: Mon Mar 18 01:27:13 2013
New Revision: 177246

URL: http://llvm.org/viewvc/llvm-project?rev=177246&view=rev
Log:
[Sanitizer] Get rid of global mutexes in StopTheWorld implementation

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld.h?rev=177246&r1=177245&r2=177246&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld.h Mon Mar 18 01:27:13 2013
@@ -60,6 +60,7 @@ typedef void (*StopTheWorldCallback)(
 // Suspend all threads in the current process and run the callback on the list
 // of suspended threads. This function will resume the threads before returning.
 // The callback should not call any libc functions.
+// This function should NOT be called from multiple threads simultaneously.
 void StopTheWorld(StopTheWorldCallback callback, void *argument);
 
 }  // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc?rev=177246&r1=177245&r2=177246&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc Mon Mar 18 01:27:13 2013
@@ -173,6 +173,9 @@ static const int kUnblockedSignals[] = {
 struct TracerThreadArgument {
   StopTheWorldCallback callback;
   void *callback_argument;
+  // The tracer thread waits on this mutex while the parent finished its
+  // preparations.
+  BlockingMutex mutex;
 };
 
 // Signal handler to wake up suspended threads when the tracer thread dies.
@@ -186,21 +189,17 @@ void TracerThreadSignalHandler(int signu
   internal__exit((signum == SIGABRT) ? 1 : 2);
 }
 
-// The tracer thread waits on this mutex while the parent finished its
-// preparations.
-static BlockingMutex tracer_init_mutex(LINKER_INITIALIZED);
-
 // Size of alternative stack for signal handlers in the tracer thread.
 static const int kHandlerStackSize = 4096;
 
 // This function will be run as a cloned task.
-int TracerThread(void* argument) {
+static int TracerThread(void* argument) {
   TracerThreadArgument *tracer_thread_argument =
       (TracerThreadArgument *)argument;
 
   // Wait for the parent thread to finish preparations.
-  tracer_init_mutex.Lock();
-  tracer_init_mutex.Unlock();
+  tracer_thread_argument->mutex.Lock();
+  tracer_thread_argument->mutex.Unlock();
 
   ThreadSuspender thread_suspender(internal_getppid());
   // Global pointer for the signal handler.
@@ -242,10 +241,7 @@ int TracerThread(void* argument) {
   return exit_code;
 }
 
-static BlockingMutex stoptheworld_mutex(LINKER_INITIALIZED);
-
 void StopTheWorld(StopTheWorldCallback callback, void *argument) {
-  BlockingMutexLock lock(&stoptheworld_mutex);
   // Block all signals that can be blocked safely, and install default handlers
   // for the remaining signals.
   // We cannot allow user-defined handlers to run while the ThreadSuspender
@@ -274,13 +270,13 @@ void StopTheWorld(StopTheWorldCallback c
   int process_was_dumpable = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
   if (!process_was_dumpable)
     internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-  // Block the execution of TracerThread until after we have set ptrace
-  // permissions.
-  tracer_init_mutex.Lock();
   // Prepare the arguments for TracerThread.
   struct TracerThreadArgument tracer_thread_argument;
   tracer_thread_argument.callback = callback;
   tracer_thread_argument.callback_argument = argument;
+  // Block the execution of TracerThread until after we have set ptrace
+  // permissions.
+  tracer_thread_argument.mutex.Lock();
   // The tracer thread will run on the same stack, so we must reserve some
   // stack space for the caller thread to run in as it waits on the tracer.
   const uptr kReservedStackSize = 4096;
@@ -292,7 +288,7 @@ void StopTheWorld(StopTheWorldCallback c
                           &tracer_thread_argument, 0, 0, 0);
   if (tracer_pid < 0) {
     Report("Failed spawning a tracer thread (errno %d).\n", errno);
-    tracer_init_mutex.Unlock();
+    tracer_thread_argument.mutex.Unlock();
   } else {
     // On some systems we have to explicitly declare that we want to be traced
     // by the tracer thread.
@@ -300,7 +296,7 @@ void StopTheWorld(StopTheWorldCallback c
     internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
 #endif
     // Allow the tracer thread to start.
-    tracer_init_mutex.Unlock();
+    tracer_thread_argument.mutex.Unlock();
     // Since errno is shared between this thread and the tracer thread, we
     // must avoid using errno while the tracer thread is running.
     // At this point, any signal will either be blocked or kill us, so waitpid





More information about the llvm-commits mailing list