[compiler-rt] r358802 - [TSan] Support fiber API on macOS

Julian Lettner via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 19 17:18:44 PDT 2019


Author: yln
Date: Fri Apr 19 17:18:44 2019
New Revision: 358802

URL: http://llvm.org/viewvc/llvm-project?rev=358802&view=rev
Log:
[TSan] Support fiber API on macOS

Committing on behalf of Yuri Per (yuri).

Reviewers: dvyukov, kubamracek, yln

Reviewed By: kubamracek

Authored By: yuri

Differential Revision: https://reviews.llvm.org/D58110

Added:
    compiler-rt/trunk/test/sanitizer_common/sanitizer_ucontext.h
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
    compiler-rt/trunk/test/lsan/TestCases/swapcontext.cc
    compiler-rt/trunk/test/tsan/fiber_asm.cc
    compiler-rt/trunk/test/tsan/fiber_from_thread.cc
    compiler-rt/trunk/test/tsan/fiber_longjmp.cc
    compiler-rt/trunk/test/tsan/fiber_race.cc
    compiler-rt/trunk/test/tsan/fiber_simple.cc
    compiler-rt/trunk/test/tsan/fiber_two_threads.cc
    compiler-rt/trunk/test/tsan/test.h

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc Fri Apr 19 17:18:44 2019
@@ -20,8 +20,10 @@
 #include "tsan_interface_ann.h"
 #include "sanitizer_common/sanitizer_addrhashmap.h"
 
+#include <errno.h>
 #include <libkern/OSAtomic.h>
 #include <objc/objc-sync.h>
+#include <sys/ucontext.h>
 
 #if defined(__has_include) && __has_include(<xpc/xpc.h>)
 #include <xpc/xpc.h>
@@ -29,6 +31,11 @@
 
 typedef long long_t;  // NOLINT
 
+extern "C" {
+int getcontext(ucontext_t *ucp) __attribute__((returns_twice));
+int setcontext(const ucontext_t *ucp);
+}
+
 namespace __tsan {
 
 // The non-barrier versions of OSAtomic* functions are semantically mo_relaxed,
@@ -353,6 +360,31 @@ TSAN_INTERCEPTOR(int, objc_sync_exit, id
   return result;
 }
 
+TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {
+  {
+    SCOPED_INTERCEPTOR_RAW(swapcontext, oucp, ucp);
+  }
+  // Bacause of swapcontext() semantics we have no option but to copy its
+  // impementation here
+  if (!oucp || !ucp) {
+    errno = EINVAL;
+    return -1;
+  }
+  ThreadState *thr = cur_thread();
+  const int UCF_SWAPPED = 0x80000000;
+  oucp->uc_onstack &= ~UCF_SWAPPED;
+  thr->ignore_interceptors++;
+  int ret = getcontext(oucp);
+  if (!(oucp->uc_onstack & UCF_SWAPPED)) {
+    thr->ignore_interceptors--;
+    if (!ret) {
+      oucp->uc_onstack |= UCF_SWAPPED;
+      ret = setcontext(ucp);
+    }
+  }
+  return ret;
+}
+
 // On macOS, libc++ is always linked dynamically, so intercepting works the
 // usual way.
 #define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc Fri Apr 19 17:18:44 2019
@@ -125,7 +125,6 @@ void __sanitizer_unaligned_store64(uu64
   *addr = v;
 }
 
-#if !SANITIZER_MAC && !SANITIZER_ANDROID
 SANITIZER_INTERFACE_ATTRIBUTE
 void *__tsan_get_current_fiber() {
   return cur_thread();
@@ -150,7 +149,6 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_set_fiber_name(void *fiber, const char *name) {
   ThreadSetName(static_cast<ThreadState *>(fiber), name);
 }
-#endif // !SANITIZER_MAC && !SANITIZER_ANDROID
 }  // extern "C"
 
 void __tsan_acquire(void *addr) {

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Fri Apr 19 17:18:44 2019
@@ -401,6 +401,10 @@ ThreadState *cur_thread() {
   return thr;
 }
 
+void set_cur_thread(ThreadState *thr) {
+  *get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
+}
+
 void cur_thread_finalize() {
   __sanitizer_sigset_t emptyset;
   internal_sigfillset(&emptyset);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc Fri Apr 19 17:18:44 2019
@@ -73,22 +73,22 @@ static void *SignalSafeGetOrAllocate(upt
 // shadow memory is set up.
 static uptr main_thread_identity = 0;
 ALIGNED(64) static char main_thread_state[sizeof(ThreadState)];
+static ThreadState *main_thread_state_loc = (ThreadState *)main_thread_state;
 
-ThreadState **cur_thread_location() {
-  ThreadState **thread_identity = (ThreadState **)pthread_self();
-  return ((uptr)thread_identity == main_thread_identity) ? nullptr
-                                                         : thread_identity;
+static ThreadState **cur_thread_location() {
+  uptr thread_identity = (uptr)pthread_self();
+  if (thread_identity == main_thread_identity || main_thread_identity == 0)
+    return &main_thread_state_loc;
+  return (ThreadState **)MemToShadow(thread_identity);
 }
 
 ThreadState *cur_thread() {
-  ThreadState **thr_state_loc = cur_thread_location();
-  if (thr_state_loc == nullptr || main_thread_identity == 0) {
-    return (ThreadState *)&main_thread_state;
-  }
-  ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc);
-  ThreadState *thr = (ThreadState *)SignalSafeGetOrAllocate(
-      (uptr *)fake_tls, sizeof(ThreadState));
-  return thr;
+  return (ThreadState *)SignalSafeGetOrAllocate(
+      (uptr *)cur_thread_location(), sizeof(ThreadState));
+}
+
+void set_cur_thread(ThreadState *thr) {
+  *cur_thread_location() = thr;
 }
 
 // TODO(kuba.brecka): This is not async-signal-safe. In particular, we call
@@ -96,14 +96,13 @@ ThreadState *cur_thread() {
 // handler will try to access the unmapped ThreadState.
 void cur_thread_finalize() {
   ThreadState **thr_state_loc = cur_thread_location();
-  if (thr_state_loc == nullptr) {
+  if (thr_state_loc == &main_thread_state_loc) {
     // Calling dispatch_main() or xpc_main() actually invokes pthread_exit to
     // exit the main thread. Let's keep the main thread's ThreadState.
     return;
   }
-  ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc);
-  internal_munmap(*fake_tls, sizeof(ThreadState));
-  *fake_tls = nullptr;
+  internal_munmap(*thr_state_loc, sizeof(ThreadState));
+  *thr_state_loc = nullptr;
 }
 #endif
 
@@ -265,11 +264,11 @@ void ImitateTlsWrite(ThreadState *thr, u
   // The pointer to the ThreadState object is stored in the shadow memory
   // of the tls.
   uptr tls_end = tls_addr + tls_size;
-  ThreadState **thr_state_loc = cur_thread_location();
-  if (thr_state_loc == nullptr) {
+  uptr thread_identity = (uptr)pthread_self();
+  if (thread_identity == main_thread_identity) {
     MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, tls_size);
   } else {
-    uptr thr_state_start = (uptr)thr_state_loc;
+    uptr thr_state_start = thread_identity;
     uptr thr_state_end = thr_state_start + sizeof(uptr);
     CHECK_GE(thr_state_start, tls_addr);
     CHECK_LE(thr_state_start, tls_addr + tls_size);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Fri Apr 19 17:18:44 2019
@@ -464,6 +464,7 @@ struct ThreadState {
 #if !SANITIZER_GO
 #if SANITIZER_MAC || SANITIZER_ANDROID
 ThreadState *cur_thread();
+void set_cur_thread(ThreadState *thr);
 void cur_thread_finalize();
 INLINE void cur_thread_init() { }
 #else

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Fri Apr 19 17:18:44 2019
@@ -405,7 +405,7 @@ void MemoryAccessRange(ThreadState *thr,
   }
 }
 
-#if !SANITIZER_MAC && !SANITIZER_ANDROID && !SANITIZER_GO
+#if !SANITIZER_GO
 void FiberSwitchImpl(ThreadState *from, ThreadState *to) {
   Processor *proc = from->proc();
   ProcUnwire(proc, from);

Modified: compiler-rt/trunk/test/lsan/TestCases/swapcontext.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/swapcontext.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/lsan/TestCases/swapcontext.cc (original)
+++ compiler-rt/trunk/test/lsan/TestCases/swapcontext.cc Fri Apr 19 17:18:44 2019
@@ -6,13 +6,8 @@
 // RUN: %env_lsan_opts= not %run %t foo 2>&1 | FileCheck %s
 // UNSUPPORTED: arm,powerpc64
 
+#include "sanitizer_common/sanitizer_ucontext.h"
 #include <stdio.h>
-#if defined(__APPLE__)
-// Note: ucontext.h is deprecated on OSX, so this test may stop working
-// someday. We define _XOPEN_SOURCE to keep using ucontext.h for now.
-#define _XOPEN_SOURCE 1
-#endif
-#include <ucontext.h>
 #include <unistd.h>
 
 const int kStackSize = 1 << 20;

Added: compiler-rt/trunk/test/sanitizer_common/sanitizer_ucontext.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/sanitizer_ucontext.h?rev=358802&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/sanitizer_ucontext.h (added)
+++ compiler-rt/trunk/test/sanitizer_common/sanitizer_ucontext.h Fri Apr 19 17:18:44 2019
@@ -0,0 +1,11 @@
+#ifdef __APPLE__
+// ucontext.h is deprecated on macOS, so tests that include it may stop working
+// someday. We define _XOPEN_SOURCE to keep using ucontext.h for now.
+#ifdef _STRUCT_UCONTEXT
+#error incomplete ucontext_t already defined, change #include order
+#endif
+#define _XOPEN_SOURCE 700
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+#include <ucontext.h>

Modified: compiler-rt/trunk/test/tsan/fiber_asm.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_asm.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_asm.cc (original)
+++ compiler-rt/trunk/test/tsan/fiber_asm.cc Fri Apr 19 17:18:44 2019
@@ -1,6 +1,6 @@
 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
 // REQUIRES: x86_64-target-arch
-// UNSUPPORTED: darwin
+// UNSUPPORTED: tvos, watchos
 #include "test.h"
 
 struct ucontext {
@@ -13,8 +13,8 @@ extern "C" {
   void ucontext_trampoline();
 }
 
-__asm__(".global ucontext_do_switch\n"
-        "ucontext_do_switch:\n\t"
+__asm__(".global " ASM_SYMBOL(ucontext_do_switch) "\n"
+        ASM_SYMBOL(ucontext_do_switch) ":\n\t"
         "pushq %rbp\n\t"
         "pushq %r15\n\t"
         "pushq %r14\n\t"
@@ -31,8 +31,8 @@ __asm__(".global ucontext_do_switch\n"
         "popq %rbp\n\t"
         "retq");
 
-__asm__(".global ucontext_trampoline\n"
-        "ucontext_trampoline:\n\t"
+__asm__(".global " ASM_SYMBOL(ucontext_trampoline) "\n"
+        ASM_SYMBOL(ucontext_trampoline) ":\n\t"
         ".cfi_startproc\n\t"
         ".cfi_undefined rip\n\t"
         "movq %r12, %rdi\n\t"

Modified: compiler-rt/trunk/test/tsan/fiber_from_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_from_thread.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_from_thread.cc (original)
+++ compiler-rt/trunk/test/tsan/fiber_from_thread.cc Fri Apr 19 17:18:44 2019
@@ -1,7 +1,7 @@
 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// UNSUPPORTED: darwin
+// UNSUPPORTED: tvos, watchos
+#include "sanitizer_common/sanitizer_ucontext.h"
 #include "test.h"
-#include <ucontext.h>
 
 char stack[64 * 1024] __attribute__((aligned(16)));
 

Modified: compiler-rt/trunk/test/tsan/fiber_longjmp.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_longjmp.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_longjmp.cc (original)
+++ compiler-rt/trunk/test/tsan/fiber_longjmp.cc Fri Apr 19 17:18:44 2019
@@ -1,8 +1,8 @@
 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// UNSUPPORTED: darwin
+// UNSUPPORTED: tvos, watchos
+#include "sanitizer_common/sanitizer_ucontext.h"
 #include "test.h"
 #include <setjmp.h>
-#include <ucontext.h>
 
 char stack[64 * 1024] __attribute__((aligned(16)));
 

Modified: compiler-rt/trunk/test/tsan/fiber_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_race.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_race.cc (original)
+++ compiler-rt/trunk/test/tsan/fiber_race.cc Fri Apr 19 17:18:44 2019
@@ -1,7 +1,7 @@
 // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
-// UNSUPPORTED: darwin
+// UNSUPPORTED: tvos, watchos
+#include "sanitizer_common/sanitizer_ucontext.h"
 #include "test.h"
-#include <ucontext.h>
 
 char stack[64 * 1024] __attribute__((aligned(16)));
 

Modified: compiler-rt/trunk/test/tsan/fiber_simple.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_simple.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_simple.cc (original)
+++ compiler-rt/trunk/test/tsan/fiber_simple.cc Fri Apr 19 17:18:44 2019
@@ -1,7 +1,7 @@
 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// UNSUPPORTED: darwin
+// UNSUPPORTED: tvos, watchos
+#include "sanitizer_common/sanitizer_ucontext.h"
 #include "test.h"
-#include <ucontext.h>
 
 char stack[64 * 1024] __attribute__((aligned(16)));
 

Modified: compiler-rt/trunk/test/tsan/fiber_two_threads.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_two_threads.cc?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_two_threads.cc (original)
+++ compiler-rt/trunk/test/tsan/fiber_two_threads.cc Fri Apr 19 17:18:44 2019
@@ -1,7 +1,7 @@
 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// UNSUPPORTED: darwin
+// UNSUPPORTED: tvos, watchos
+#include "sanitizer_common/sanitizer_ucontext.h"
 #include "test.h"
-#include <ucontext.h>
 
 char stack[64 * 1024] __attribute__((aligned(16)));
 

Modified: compiler-rt/trunk/test/tsan/test.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/test.h?rev=358802&r1=358801&r2=358802&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/test.h (original)
+++ compiler-rt/trunk/test/tsan/test.h Fri Apr 19 17:18:44 2019
@@ -89,3 +89,9 @@ void AnnotateRWLockReleased(const char *
     AnnotateRWLockAcquired(__FILE__, __LINE__, m, is_w)
 #define ANNOTATE_RWLOCK_RELEASED(m, is_w) \
     AnnotateRWLockReleased(__FILE__, __LINE__, m, is_w)
+
+#ifdef __APPLE__
+#define ASM_SYMBOL(symbol) "_" #symbol
+#else
+#define ASM_SYMBOL(symbol) #symbol
+#endif




More information about the llvm-commits mailing list