[compiler-rt] r353817 - tsan: add fiber support
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 12 02:11:59 PST 2019
Author: dvyukov
Date: Tue Feb 12 02:11:58 2019
New Revision: 353817
URL: http://llvm.org/viewvc/llvm-project?rev=353817&view=rev
Log:
tsan: add fiber support
This patch adds functions for managing fibers:
__tsan_get_current_fiber()
__tsan_create_fiber()
__tsan_destroy_fiber()
__tsan_switch_to_fiber()
__tsan_set_fiber_name()
See the added tests for use examples.
Author: yuri (Yuri Per)
Reviewed in: https://reviews.llvm.org/D54889
Added:
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
Modified:
compiler-rt/trunk/include/sanitizer/tsan_interface.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h
compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
Modified: compiler-rt/trunk/include/sanitizer/tsan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/tsan_interface.h?rev=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/tsan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/tsan_interface.h Tue Feb 12 02:11:58 2019
@@ -136,6 +136,24 @@ void __tsan_external_assign_tag(void *ad
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
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h?rev=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h Tue Feb 12 02:11:58 2019
@@ -31,6 +31,7 @@ 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.
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Tue Feb 12 02:11:58 2019
@@ -554,6 +554,7 @@ static void LongJmp(ThreadState *thr, up
// 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);
}
@@ -942,6 +943,7 @@ extern "C" void *__tsan_thread_start_fun
void *param = p->param;
int tid = 0;
{
+ cur_thread_init();
ThreadState *thr = cur_thread();
// Thread-local state is not initialized yet.
ScopedIgnoreInterceptors ignore;
@@ -1053,6 +1055,9 @@ TSAN_INTERCEPTOR(int, pthread_detach, vo
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);
}
@@ -1981,6 +1986,7 @@ static bool is_sync_signal(ThreadSignalC
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) {
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h?rev=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h Tue Feb 12 02:11:58 2019
@@ -23,6 +23,7 @@ LibIgnore *libignore();
#if !SANITIZER_GO
INLINE bool in_symbolizer() {
+ cur_thread_init();
return UNLIKELY(cur_thread()->in_symbolizer);
}
#endif
@@ -30,6 +31,7 @@ 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); \
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=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface.cc Tue Feb 12 02:11:58 2019
@@ -24,6 +24,7 @@ typedef u32 uint32_t;
typedef u64 uint64_t;
void __tsan_init() {
+ cur_thread_init();
Initialize(cur_thread());
}
@@ -123,6 +124,33 @@ void __sanitizer_unaligned_store64(uu64
__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) {
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=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Tue Feb 12 02:11:58 2019
@@ -384,6 +384,9 @@ 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.
@@ -462,11 +465,20 @@ 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);
+ 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;
}
INLINE void cur_thread_finalize() { }
#endif // SANITIZER_MAC || SANITIZER_ANDROID
@@ -868,6 +880,16 @@ 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
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=353817&r1=353816&r2=353817&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Tue Feb 12 02:11:58 2019
@@ -246,7 +246,8 @@ void ThreadStart(ThreadState *thr, int t
uptr tls_addr = 0;
uptr tls_size = 0;
#if !SANITIZER_GO
- GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
+ if (thread_type != ThreadType::Fiber)
+ GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
if (tid) {
if (stk_addr && stk_size)
@@ -404,4 +405,40 @@ void MemoryAccessRange(ThreadState *thr,
}
}
+#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
Added: compiler-rt/trunk/test/tsan/fiber_asm.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_asm.cc?rev=353817&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_asm.cc (added)
+++ compiler-rt/trunk/test/tsan/fiber_asm.cc Tue Feb 12 02:11:58 2019
@@ -0,0 +1,86 @@
+// 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
Added: 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=353817&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_from_thread.cc (added)
+++ compiler-rt/trunk/test/tsan/fiber_from_thread.cc Tue Feb 12 02:11:58 2019
@@ -0,0 +1,48 @@
+// 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
Added: compiler-rt/trunk/test/tsan/fiber_longjmp.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_longjmp.cc?rev=353817&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_longjmp.cc (added)
+++ compiler-rt/trunk/test/tsan/fiber_longjmp.cc Tue Feb 12 02:11:58 2019
@@ -0,0 +1,80 @@
+// 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
Added: compiler-rt/trunk/test/tsan/fiber_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_race.cc?rev=353817&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_race.cc (added)
+++ compiler-rt/trunk/test/tsan/fiber_race.cc Tue Feb 12 02:11:58 2019
@@ -0,0 +1,36 @@
+// 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
Added: compiler-rt/trunk/test/tsan/fiber_simple.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/fiber_simple.cc?rev=353817&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_simple.cc (added)
+++ compiler-rt/trunk/test/tsan/fiber_simple.cc Tue Feb 12 02:11:58 2019
@@ -0,0 +1,36 @@
+// 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
Added: 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=353817&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/fiber_two_threads.cc (added)
+++ compiler-rt/trunk/test/tsan/fiber_two_threads.cc Tue Feb 12 02:11:58 2019
@@ -0,0 +1,62 @@
+// 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
More information about the llvm-commits
mailing list