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 #include <setjmp.h> 7 8 char stack[64 * 1024] __attribute__((aligned(16))); 9 10 sigjmp_buf jmpbuf, orig_jmpbuf[2]; 11 void *fiber, *orig_fiber[2]; 12 13 const unsigned N = 1000; 14 15 __attribute__((noinline)) 16 void switch0() { 17 if (!sigsetjmp(jmpbuf, 0)) { 18 __tsan_switch_to_fiber(orig_fiber[0], 0); 19 siglongjmp(orig_jmpbuf[0], 1); 20 } 21 } 22 23 void func() { 24 if (!sigsetjmp(jmpbuf, 0)) { 25 __tsan_switch_to_fiber(orig_fiber[0], 0); 26 siglongjmp(orig_jmpbuf[0], 1); 27 } 28 for (;;) { 29 switch0(); 30 if (!sigsetjmp(jmpbuf, 0)) { 31 __tsan_switch_to_fiber(orig_fiber[1], 0); 32 siglongjmp(orig_jmpbuf[1], 1); 33 } 34 } 35 } 36 37 void *Thread(void *x) { 38 orig_fiber[1] = __tsan_get_current_fiber(); 39 for (unsigned i = 0; i < N; i++) { 40 barrier_wait(&barrier); 41 if (!sigsetjmp(orig_jmpbuf[1], 0)) { 42 __tsan_switch_to_fiber(fiber, 0); 43 siglongjmp(jmpbuf, 1); 44 } 45 barrier_wait(&barrier); 46 } 47 return 0; 48 } 49 50 int main() { 51 fiber = __tsan_create_fiber(0); 52 barrier_init(&barrier, 2); 53 pthread_t t; 54 pthread_create(&t, 0, Thread, 0); 55 orig_fiber[0] = __tsan_get_current_fiber(); 56 ucontext_t uc, orig_uc; 57 getcontext(&uc); 58 uc.uc_stack.ss_sp = stack; 59 uc.uc_stack.ss_size = sizeof(stack); 60 uc.uc_link = 0; 61 makecontext(&uc, func, 0); 62 if (!sigsetjmp(orig_jmpbuf[0], 0)) { 63 __tsan_switch_to_fiber(fiber, 0); 64 swapcontext(&orig_uc, &uc); 65 } 66 for (unsigned i = 0; i < N; i++) { 67 if (!sigsetjmp(orig_jmpbuf[0], 0)) { 68 __tsan_switch_to_fiber(fiber, 0); 69 siglongjmp(jmpbuf, 1); 70 } 71 barrier_wait(&barrier); 72 barrier_wait(&barrier); 73 } 74 pthread_join(t, 0); 75 __tsan_destroy_fiber(fiber); 76 fprintf(stderr, "PASS\n"); 77 return 0; 78 } 79 80 // CHECK-NOT: WARNING: ThreadSanitizer: 81 // CHECK: PASS 82