1 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 // UNSUPPORTED: tvos, watchos 3 // XFAIL: ios && !iossim 4 #include "sanitizer_common/sanitizer_ucontext.h" 5 #include "test.h" 6 7 char stack[64 * 1024] __attribute__((aligned(16))); 8 9 ucontext_t uc, orig_uc[2]; 10 void *fiber, *orig_fiber[2]; 11 12 const unsigned N = 1000; 13 14 __attribute__((noinline)) 15 void switch0() { 16 __tsan_switch_to_fiber(orig_fiber[0], 0); 17 swapcontext(&uc, &orig_uc[0]); 18 } 19 20 void func() { 21 for (;;) { 22 switch0(); 23 __tsan_switch_to_fiber(orig_fiber[1], 0); 24 swapcontext(&uc, &orig_uc[1]); 25 } 26 } 27 28 void *Thread(void *x) { 29 orig_fiber[1] = __tsan_get_current_fiber(); 30 for (unsigned i = 0; i < N; i++) { 31 barrier_wait(&barrier); 32 __tsan_switch_to_fiber(fiber, 0); 33 swapcontext(&orig_uc[1], &uc); 34 barrier_wait(&barrier); 35 } 36 return 0; 37 } 38 39 int main() { 40 fiber = __tsan_create_fiber(0); 41 barrier_init(&barrier, 2); 42 pthread_t t; 43 pthread_create(&t, 0, Thread, 0); 44 orig_fiber[0] = __tsan_get_current_fiber(); 45 getcontext(&uc); 46 uc.uc_stack.ss_sp = stack; 47 uc.uc_stack.ss_size = sizeof(stack); 48 uc.uc_link = 0; 49 makecontext(&uc, func, 0); 50 for (unsigned i = 0; i < N; i++) { 51 __tsan_switch_to_fiber(fiber, 0); 52 swapcontext(&orig_uc[0], &uc); 53 barrier_wait(&barrier); 54 barrier_wait(&barrier); 55 } 56 pthread_join(t, 0); 57 __tsan_destroy_fiber(fiber); 58 fprintf(stderr, "PASS\n"); 59 return 0; 60 } 61 62 // CHECK-NOT: WARNING: ThreadSanitizer: 63 // CHECK: PASS 64