diff options
author | Diana Picus <diana.picus@linaro.org> | 2019-02-13 11:32:56 +0000 |
---|---|---|
committer | Diana Picus <diana.picus@linaro.org> | 2019-02-13 11:32:56 +0000 |
commit | 92c6f88b7bbca3e9d7ac38944be036ec47ec55b9 (patch) | |
tree | 419f538191c7e42dabc9b0997054141c2a1073ab | |
parent | ee4e9bc777b622d910b025aeb09b4b88f47e0386 (diff) | |
download | compiler-rt-92c6f88b7bbca3e9d7ac38944be036ec47ec55b9.tar.gz |
Revert "tsan: add fiber support"
This reverts commit r353817 because we think it broke AARch64 and
PowerPC buildbots.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@353939 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/sanitizer/tsan_interface.h | 18 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_thread_registry.h | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cc | 6 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.h | 2 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interface.cc | 28 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.h | 24 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_thread.cc | 39 | ||||
-rw-r--r-- | test/tsan/fiber_asm.cc | 86 | ||||
-rw-r--r-- | test/tsan/fiber_from_thread.cc | 48 | ||||
-rw-r--r-- | test/tsan/fiber_longjmp.cc | 80 | ||||
-rw-r--r-- | test/tsan/fiber_race.cc | 36 | ||||
-rw-r--r-- | test/tsan/fiber_simple.cc | 36 | ||||
-rw-r--r-- | test/tsan/fiber_two_threads.cc | 62 |
13 files changed, 2 insertions, 464 deletions
diff --git a/include/sanitizer/tsan_interface.h b/include/sanitizer/tsan_interface.h index 011b23350..4a98a4e12 100644 --- a/include/sanitizer/tsan_interface.h +++ b/include/sanitizer/tsan_interface.h @@ -136,24 +136,6 @@ void __tsan_external_assign_tag(void *addr, void *tag); void __tsan_external_read(void *addr, void *caller_pc, void *tag); void __tsan_external_write(void *addr, void *caller_pc, void *tag); -// Fiber switching API. -// - TSAN context for fiber can be created by __tsan_create_fiber -// and freed by __tsan_destroy_fiber. -// - TSAN context of current fiber or thread can be obtained -// by calling __tsan_get_current_fiber. -// - __tsan_switch_to_fiber should be called immediatly before switch -// to fiber, such as call of swapcontext. -// - Fiber name can be set by __tsan_set_fiber_name. -void *__tsan_get_current_fiber(void); -void *__tsan_create_fiber(unsigned flags); -void __tsan_destroy_fiber(void *fiber); -void __tsan_switch_to_fiber(void *fiber, unsigned flags); -void __tsan_set_fiber_name(void *fiber, const char *name); - -// Flags for __tsan_switch_to_fiber: -// Do not establish a happens-before relation between fibers -const unsigned __tsan_switch_to_fiber_no_sync = 1 << 0; - #ifdef __cplusplus } // extern "C" #endif diff --git a/lib/sanitizer_common/sanitizer_thread_registry.h b/lib/sanitizer_common/sanitizer_thread_registry.h index 493aa988f..fc38d0f80 100644 --- a/lib/sanitizer_common/sanitizer_thread_registry.h +++ b/lib/sanitizer_common/sanitizer_thread_registry.h @@ -31,7 +31,6 @@ enum ThreadStatus { enum class ThreadType { Regular, // Normal thread Worker, // macOS Grand Central Dispatch (GCD) worker thread - Fiber, // Fiber }; // Generic thread context. Specific sanitizer tools may inherit from it. diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index ef11000c0..b9f245e40 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -554,7 +554,6 @@ static void LongJmp(ThreadState *thr, uptr *env) { // FIXME: put everything below into a common extern "C" block? extern "C" void __tsan_setjmp(uptr sp, uptr mangled_sp) { - cur_thread_init(); SetJmp(cur_thread(), sp, mangled_sp); } @@ -943,7 +942,6 @@ extern "C" void *__tsan_thread_start_func(void *arg) { void *param = p->param; int tid = 0; { - cur_thread_init(); ThreadState *thr = cur_thread(); // Thread-local state is not initialized yet. ScopedIgnoreInterceptors ignore; @@ -1055,9 +1053,6 @@ TSAN_INTERCEPTOR(int, pthread_detach, void *th) { TSAN_INTERCEPTOR(void, pthread_exit, void *retval) { { SCOPED_INTERCEPTOR_RAW(pthread_exit, retval); -#if !SANITIZER_MAC && !SANITIZER_ANDROID - CHECK_EQ(thr, &cur_thread_placeholder); -#endif } REAL(pthread_exit)(retval); } @@ -1986,7 +1981,6 @@ static bool is_sync_signal(ThreadSignalContext *sctx, int sig) { void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig, __sanitizer_siginfo *info, void *ctx) { - cur_thread_init(); ThreadState *thr = cur_thread(); ThreadSignalContext *sctx = SigCtx(thr); if (sig < 0 || sig >= kSigCount) { diff --git a/lib/tsan/rtl/tsan_interceptors.h b/lib/tsan/rtl/tsan_interceptors.h index 88d1edd77..29b0f76f9 100644 --- a/lib/tsan/rtl/tsan_interceptors.h +++ b/lib/tsan/rtl/tsan_interceptors.h @@ -23,7 +23,6 @@ LibIgnore *libignore(); #if !SANITIZER_GO INLINE bool in_symbolizer() { - cur_thread_init(); return UNLIKELY(cur_thread()->in_symbolizer); } #endif @@ -31,7 +30,6 @@ INLINE bool in_symbolizer() { } // namespace __tsan #define SCOPED_INTERCEPTOR_RAW(func, ...) \ - cur_thread_init(); \ ThreadState *thr = cur_thread(); \ const uptr caller_pc = GET_CALLER_PC(); \ ScopedInterceptor si(thr, #func, caller_pc); \ diff --git a/lib/tsan/rtl/tsan_interface.cc b/lib/tsan/rtl/tsan_interface.cc index 8101ba193..09a840152 100644 --- a/lib/tsan/rtl/tsan_interface.cc +++ b/lib/tsan/rtl/tsan_interface.cc @@ -24,7 +24,6 @@ typedef u32 uint32_t; typedef u64 uint64_t; void __tsan_init() { - cur_thread_init(); Initialize(cur_thread()); } @@ -124,33 +123,6 @@ void __sanitizer_unaligned_store64(uu64 *addr, u64 v) { __tsan_unaligned_write8(addr); *addr = v; } - -#if !SANITIZER_MAC && !SANITIZER_ANDROID -SANITIZER_INTERFACE_ATTRIBUTE -void *__tsan_get_current_fiber() { - return cur_thread(); -} - -SANITIZER_INTERFACE_ATTRIBUTE -void *__tsan_create_fiber(unsigned flags) { - return FiberCreate(cur_thread(), CALLERPC, flags); -} - -SANITIZER_INTERFACE_ATTRIBUTE -void __tsan_destroy_fiber(void *fiber) { - FiberDestroy(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber)); -} - -SANITIZER_INTERFACE_ATTRIBUTE -void __tsan_switch_to_fiber(void *fiber, unsigned flags) { - FiberSwitch(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber), flags); -} - -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) { diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index 1804deaf5..37ca731e9 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -384,9 +384,6 @@ struct ThreadState { // taken by epoch between synchs. // This way we can save one load from tls. u64 fast_synch_epoch; - // Technically `current` should be a separate THREADLOCAL variable; - // but it is placed here in order to share cache line with previous fields. - ThreadState* current; // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read. // We do not distinguish beteween ignoring reads and writes // for better performance. @@ -465,20 +462,11 @@ struct ThreadState { #if SANITIZER_MAC || SANITIZER_ANDROID ThreadState *cur_thread(); void cur_thread_finalize(); -INLINE void cur_thread_init() { } #else __attribute__((tls_model("initial-exec"))) extern THREADLOCAL char cur_thread_placeholder[]; INLINE ThreadState *cur_thread() { - return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current; -} -INLINE void cur_thread_init() { - ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder); - if (UNLIKELY(!thr->current)) - thr->current = thr; -} -INLINE void set_cur_thread(ThreadState *thr) { - reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr; + return reinterpret_cast<ThreadState *>(&cur_thread_placeholder); } INLINE void cur_thread_finalize() { } #endif // SANITIZER_MAC || SANITIZER_ANDROID @@ -880,16 +868,6 @@ uptr ALWAYS_INLINE HeapEnd() { } #endif -ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags); -void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber); -void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags); - -// These need to match __tsan_switch_to_fiber_* flags defined in -// tsan_interface.h. See documentation there as well. -enum FiberSwitchFlags { - FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync -}; - } // namespace __tsan #endif // TSAN_RTL_H diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc index 605134894..de429a553 100644 --- a/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/lib/tsan/rtl/tsan_rtl_thread.cc @@ -246,8 +246,7 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, uptr tls_addr = 0; uptr tls_size = 0; #if !SANITIZER_GO - if (thread_type != ThreadType::Fiber) - GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size); + GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size); if (tid) { if (stk_addr && stk_size) @@ -405,40 +404,4 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, } } -#if !SANITIZER_MAC && !SANITIZER_ANDROID && !SANITIZER_GO -void FiberSwitchImpl(ThreadState *from, ThreadState *to) { - Processor *proc = from->proc(); - ProcUnwire(proc, from); - ProcWire(proc, to); - set_cur_thread(to); -} - -ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) { - void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadState)); - ThreadState *fiber = static_cast<ThreadState *>(mem); - internal_memset(fiber, 0, sizeof(*fiber)); - int tid = ThreadCreate(thr, pc, 0, true); - FiberSwitchImpl(thr, fiber); - ThreadStart(fiber, tid, 0, ThreadType::Fiber); - FiberSwitchImpl(fiber, thr); - return fiber; -} - -void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) { - FiberSwitchImpl(thr, fiber); - ThreadFinish(fiber); - FiberSwitchImpl(fiber, thr); - internal_free(fiber); -} - -void FiberSwitch(ThreadState *thr, uptr pc, - ThreadState *fiber, unsigned flags) { - if (!(flags & FiberSwitchFlagNoSync)) - Release(thr, pc, (uptr)fiber); - FiberSwitchImpl(thr, fiber); - if (!(flags & FiberSwitchFlagNoSync)) - Acquire(fiber, pc, (uptr)fiber); -} -#endif - } // namespace __tsan diff --git a/test/tsan/fiber_asm.cc b/test/tsan/fiber_asm.cc deleted file mode 100644 index 806c70cce..000000000 --- a/test/tsan/fiber_asm.cc +++ /dev/null @@ -1,86 +0,0 @@ -// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// REQUIRES: x86_64-target-arch -// UNSUPPORTED: darwin -#include "test.h" - -struct ucontext { - void *sp; - void *fiber; -}; - -extern "C" { - void ucontext_do_switch(void **save, void **load); - void ucontext_trampoline(); -} - -__asm__(".global ucontext_do_switch\n" - "ucontext_do_switch:\n\t" - "pushq %rbp\n\t" - "pushq %r15\n\t" - "pushq %r14\n\t" - "pushq %r13\n\t" - "pushq %r12\n\t" - "pushq %rbx\n\t" - "movq %rsp, (%rdi)\n\t" - "movq (%rsi), %rsp\n\t" - "popq %rbx\n\t" - "popq %r12\n\t" - "popq %r13\n\t" - "popq %r14\n\t" - "popq %r15\n\t" - "popq %rbp\n\t" - "retq"); - -__asm__(".global ucontext_trampoline\n" - "ucontext_trampoline:\n\t" - ".cfi_startproc\n\t" - ".cfi_undefined rip\n\t" - "movq %r12, %rdi\n\t" - "jmpq *%rbx\n\t" - ".cfi_endproc"); - -void ucontext_init(ucontext *context, void *stack, unsigned stack_sz, - void (*func)(void*), void *arg) { - void **sp = reinterpret_cast<void **>(static_cast<char *>(stack) + stack_sz); - *(--sp) = 0; - *(--sp) = reinterpret_cast<void *>(ucontext_trampoline); - *(--sp) = 0; // rbp - *(--sp) = 0; // r15 - *(--sp) = 0; // r14 - *(--sp) = 0; // r13 - *(--sp) = arg; // r12 - *(--sp) = reinterpret_cast<void *>(func); // rbx - context->sp = sp; - context->fiber = __tsan_create_fiber(0); -} - -void ucontext_free(ucontext *context) { - __tsan_destroy_fiber(context->fiber); -} - -__attribute__((no_sanitize_thread)) -void ucontext_switch(ucontext *save, ucontext *load) { - save->fiber = __tsan_get_current_fiber(); - __tsan_switch_to_fiber(load->fiber, 0); - ucontext_do_switch(&save->sp, &load->sp); -} - -char stack[64 * 1024] __attribute__((aligned(16))); - -ucontext uc, orig_uc; - -void func(void *arg) { - __asm__ __volatile__(".cfi_undefined rip"); - ucontext_switch(&uc, &orig_uc); -} - -int main() { - ucontext_init(&uc, stack, sizeof(stack), func, 0); - ucontext_switch(&orig_uc, &uc); - ucontext_free(&uc); - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK-NOT: WARNING: ThreadSanitizer: -// CHECK: PASS diff --git a/test/tsan/fiber_from_thread.cc b/test/tsan/fiber_from_thread.cc deleted file mode 100644 index d8af1e8e7..000000000 --- a/test/tsan/fiber_from_thread.cc +++ /dev/null @@ -1,48 +0,0 @@ -// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// UNSUPPORTED: darwin -#include "test.h" -#include <ucontext.h> - -char stack[64 * 1024] __attribute__((aligned(16))); - -ucontext_t uc, orig_uc1, orig_uc2; -void *fiber, *orig_fiber1, *orig_fiber2; - -int var; - -void *Thread(void *x) { - orig_fiber2 = __tsan_get_current_fiber(); - swapcontext(&orig_uc2, &orig_uc1); - return 0; -} - -void func() { - pthread_t t; - pthread_create(&t, 0, Thread, 0); - pthread_join(t, 0); - __tsan_switch_to_fiber(orig_fiber1, 0); - swapcontext(&uc, &orig_uc1); -} - -int main() { - orig_fiber1 = __tsan_get_current_fiber(); - fiber = __tsan_create_fiber(0); - getcontext(&uc); - uc.uc_stack.ss_sp = stack; - uc.uc_stack.ss_size = sizeof(stack); - uc.uc_link = 0; - makecontext(&uc, func, 0); - var = 1; - __tsan_switch_to_fiber(fiber, 0); - swapcontext(&orig_uc1, &uc); - var = 2; - __tsan_switch_to_fiber(orig_fiber2, 0); - swapcontext(&orig_uc1, &orig_uc2); - var = 3; - __tsan_destroy_fiber(fiber); - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK-NOT: WARNING: ThreadSanitizer: -// CHECK: PASS diff --git a/test/tsan/fiber_longjmp.cc b/test/tsan/fiber_longjmp.cc deleted file mode 100644 index 27d776a78..000000000 --- a/test/tsan/fiber_longjmp.cc +++ /dev/null @@ -1,80 +0,0 @@ -// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// UNSUPPORTED: darwin -#include "test.h" -#include <setjmp.h> -#include <ucontext.h> - -char stack[64 * 1024] __attribute__((aligned(16))); - -sigjmp_buf jmpbuf, orig_jmpbuf[2]; -void *fiber, *orig_fiber[2]; - -const unsigned N = 1000; - -__attribute__((noinline)) -void switch0() { - if (!sigsetjmp(jmpbuf, 0)) { - __tsan_switch_to_fiber(orig_fiber[0], 0); - siglongjmp(orig_jmpbuf[0], 1); - } -} - -void func() { - if (!sigsetjmp(jmpbuf, 0)) { - __tsan_switch_to_fiber(orig_fiber[0], 0); - siglongjmp(orig_jmpbuf[0], 1); - } - for (;;) { - switch0(); - if (!sigsetjmp(jmpbuf, 0)) { - __tsan_switch_to_fiber(orig_fiber[1], 0); - siglongjmp(orig_jmpbuf[1], 1); - } - } -} - -void *Thread(void *x) { - orig_fiber[1] = __tsan_get_current_fiber(); - for (unsigned i = 0; i < N; i++) { - barrier_wait(&barrier); - if (!sigsetjmp(orig_jmpbuf[1], 0)) { - __tsan_switch_to_fiber(fiber, 0); - siglongjmp(jmpbuf, 1); - } - barrier_wait(&barrier); - } - return 0; -} - -int main() { - fiber = __tsan_create_fiber(0); - barrier_init(&barrier, 2); - pthread_t t; - pthread_create(&t, 0, Thread, 0); - orig_fiber[0] = __tsan_get_current_fiber(); - ucontext_t uc, orig_uc; - getcontext(&uc); - uc.uc_stack.ss_sp = stack; - uc.uc_stack.ss_size = sizeof(stack); - uc.uc_link = 0; - makecontext(&uc, func, 0); - if (!sigsetjmp(orig_jmpbuf[0], 0)) { - __tsan_switch_to_fiber(fiber, 0); - swapcontext(&orig_uc, &uc); - } - for (unsigned i = 0; i < N; i++) { - if (!sigsetjmp(orig_jmpbuf[0], 0)) { - __tsan_switch_to_fiber(fiber, 0); - siglongjmp(jmpbuf, 1); - } - barrier_wait(&barrier); - barrier_wait(&barrier); - } - pthread_join(t, 0); - __tsan_destroy_fiber(fiber); - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK-NOT: WARNING: ThreadSanitizer: -// CHECK: PASS diff --git a/test/tsan/fiber_race.cc b/test/tsan/fiber_race.cc deleted file mode 100644 index 89bcdddd5..000000000 --- a/test/tsan/fiber_race.cc +++ /dev/null @@ -1,36 +0,0 @@ -// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s -// UNSUPPORTED: darwin -#include "test.h" -#include <ucontext.h> - -char stack[64 * 1024] __attribute__((aligned(16))); - -ucontext_t uc, orig_uc; -void *fiber, *orig_fiber; - -int var; - -void func() { - var = 1; - __tsan_switch_to_fiber(orig_fiber, __tsan_switch_to_fiber_no_sync); - swapcontext(&uc, &orig_uc); -} - -int main() { - orig_fiber = __tsan_get_current_fiber(); - fiber = __tsan_create_fiber(0); - getcontext(&uc); - uc.uc_stack.ss_sp = stack; - uc.uc_stack.ss_size = sizeof(stack); - uc.uc_link = 0; - makecontext(&uc, func, 0); - var = 2; - __tsan_switch_to_fiber(fiber, __tsan_switch_to_fiber_no_sync); - swapcontext(&orig_uc, &uc); - __tsan_destroy_fiber(fiber); - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK: WARNING: ThreadSanitizer: data race -// CHECK: PASS diff --git a/test/tsan/fiber_simple.cc b/test/tsan/fiber_simple.cc deleted file mode 100644 index ce529e729..000000000 --- a/test/tsan/fiber_simple.cc +++ /dev/null @@ -1,36 +0,0 @@ -// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// UNSUPPORTED: darwin -#include "test.h" -#include <ucontext.h> - -char stack[64 * 1024] __attribute__((aligned(16))); - -ucontext_t uc, orig_uc; -void *fiber, *orig_fiber; - -int var; - -void func() { - var = 1; - __tsan_switch_to_fiber(orig_fiber, 0); - swapcontext(&uc, &orig_uc); -} - -int main() { - orig_fiber = __tsan_get_current_fiber(); - fiber = __tsan_create_fiber(0); - getcontext(&uc); - uc.uc_stack.ss_sp = stack; - uc.uc_stack.ss_size = sizeof(stack); - uc.uc_link = 0; - makecontext(&uc, func, 0); - var = 2; - __tsan_switch_to_fiber(fiber, 0); - swapcontext(&orig_uc, &uc); - __tsan_destroy_fiber(fiber); - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK-NOT: WARNING: ThreadSanitizer: -// CHECK: PASS diff --git a/test/tsan/fiber_two_threads.cc b/test/tsan/fiber_two_threads.cc deleted file mode 100644 index eaadb65ac..000000000 --- a/test/tsan/fiber_two_threads.cc +++ /dev/null @@ -1,62 +0,0 @@ -// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// UNSUPPORTED: darwin -#include "test.h" -#include <ucontext.h> - -char stack[64 * 1024] __attribute__((aligned(16))); - -ucontext_t uc, orig_uc[2]; -void *fiber, *orig_fiber[2]; - -const unsigned N = 1000; - -__attribute__((noinline)) -void switch0() { - __tsan_switch_to_fiber(orig_fiber[0], 0); - swapcontext(&uc, &orig_uc[0]); -} - -void func() { - for (;;) { - switch0(); - __tsan_switch_to_fiber(orig_fiber[1], 0); - swapcontext(&uc, &orig_uc[1]); - } -} - -void *Thread(void *x) { - orig_fiber[1] = __tsan_get_current_fiber(); - for (unsigned i = 0; i < N; i++) { - barrier_wait(&barrier); - __tsan_switch_to_fiber(fiber, 0); - swapcontext(&orig_uc[1], &uc); - barrier_wait(&barrier); - } - return 0; -} - -int main() { - fiber = __tsan_create_fiber(0); - barrier_init(&barrier, 2); - pthread_t t; - pthread_create(&t, 0, Thread, 0); - orig_fiber[0] = __tsan_get_current_fiber(); - getcontext(&uc); - uc.uc_stack.ss_sp = stack; - uc.uc_stack.ss_size = sizeof(stack); - uc.uc_link = 0; - makecontext(&uc, func, 0); - for (unsigned i = 0; i < N; i++) { - __tsan_switch_to_fiber(fiber, 0); - swapcontext(&orig_uc[0], &uc); - barrier_wait(&barrier); - barrier_wait(&barrier); - } - pthread_join(t, 0); - __tsan_destroy_fiber(fiber); - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK-NOT: WARNING: ThreadSanitizer: -// CHECK: PASS |