From 17ab9e64464f989b3fe4a304a450581a618097a0 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 17:44:49 -0700 Subject: [TSAN] Move test into Linux/ Linux specific test was introduced by #86537 --- .../test/tsan/Linux/signal_in_futex_wait.cpp | 116 +++++++++++++++++++++ compiler-rt/test/tsan/signal_in_futex_wait.cpp | 116 --------------------- 2 files changed, 116 insertions(+), 116 deletions(-) create mode 100644 compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp delete mode 100644 compiler-rt/test/tsan/signal_in_futex_wait.cpp diff --git a/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp new file mode 100644 index 0000000..34d058e --- /dev/null +++ b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp @@ -0,0 +1,116 @@ +// RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s + +#include "../test.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, + int *uaddr2, int val3) { + __sanitizer_syscall_pre_futex(uaddr, futex_op, val, timeout, uaddr2, val3); + int result = syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); + __sanitizer_syscall_post_futex(result, uaddr, futex_op, val, timeout, uaddr2, + val3); + return result; +} + +// Simple mutex implementation using futex. +class Mutex { +public: + Mutex() : value(0) {} + + void lock() { + int c; + while ((c = __sync_val_compare_and_swap(&value, 0, 1)) != 0) { + if (c != 1) + continue; + int r = futex(&value, FUTEX_WAIT_PRIVATE, 1, nullptr, nullptr, 0); + if (r == -1 && errno != EAGAIN) { + fprintf(stderr, "futex wait error\n"); + abort(); + } + } + } + + void unlock() { + value = 0; + int r = futex(&value, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0); + if (r == -1) { + fprintf(stderr, "futex wake error\n"); + abort(); + } + } + +private: + int value; +}; + +Mutex mutex; + +void *Thread(void *x) { + // fprintf(stderr, "canova here thread 0\n"); + // Waiting for the futex. + mutex.lock(); + // fprintf(stderr, "canova here thread 1\n"); + // Finished waiting. + return nullptr; +} + +static void SigprofHandler(int signal, siginfo_t *info, void *context) { + // fprintf(stderr, "canova here sigprof handler\n"); + // Unlock the futex. + mutex.unlock(); +} + +void InstallSignalHandler() { + struct sigaction sa; + sa.sa_sigaction = SigprofHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_SIGINFO; + if (sigaction(SIGPROF, &sa, 0) != 0) { + fprintf(stderr, "failed to install signal handler\n"); + abort(); + } +} + +int main() { + alarm(60); // Kill the test if it hangs. + + // Install the signal handler + InstallSignalHandler(); + + // Lock the futex at first so the other thread will wait for it. + mutex.lock(); + + // Create the thread to wait for the futex. + pthread_t thread; + pthread_create(&thread, NULL, Thread, NULL); + + // Just waiting a bit to make sure the thead is at the FUTEX_WAIT_PRIVATE + // syscall. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Send the signal to the other thread, which will send the futex wake + // syscall. + int r = pthread_kill(thread, SIGPROF); + assert(r == 0); + + // Futex should be notified and the thread should be able to continue. + pthread_join(thread, NULL); + + // Exiting successfully. + fprintf(stderr, "PASS\n"); + return 0; +} + +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: PASS diff --git a/compiler-rt/test/tsan/signal_in_futex_wait.cpp b/compiler-rt/test/tsan/signal_in_futex_wait.cpp deleted file mode 100644 index cf31e54..0000000 --- a/compiler-rt/test/tsan/signal_in_futex_wait.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s - -#include "test.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, - int *uaddr2, int val3) { - __sanitizer_syscall_pre_futex(uaddr, futex_op, val, timeout, uaddr2, val3); - int result = syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); - __sanitizer_syscall_post_futex(result, uaddr, futex_op, val, timeout, uaddr2, - val3); - return result; -} - -// Simple mutex implementation using futex. -class Mutex { -public: - Mutex() : value(0) {} - - void lock() { - int c; - while ((c = __sync_val_compare_and_swap(&value, 0, 1)) != 0) { - if (c != 1) - continue; - int r = futex(&value, FUTEX_WAIT_PRIVATE, 1, nullptr, nullptr, 0); - if (r == -1 && errno != EAGAIN) { - fprintf(stderr, "futex wait error\n"); - abort(); - } - } - } - - void unlock() { - value = 0; - int r = futex(&value, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0); - if (r == -1) { - fprintf(stderr, "futex wake error\n"); - abort(); - } - } - -private: - int value; -}; - -Mutex mutex; - -void *Thread(void *x) { - // fprintf(stderr, "canova here thread 0\n"); - // Waiting for the futex. - mutex.lock(); - // fprintf(stderr, "canova here thread 1\n"); - // Finished waiting. - return nullptr; -} - -static void SigprofHandler(int signal, siginfo_t *info, void *context) { - // fprintf(stderr, "canova here sigprof handler\n"); - // Unlock the futex. - mutex.unlock(); -} - -void InstallSignalHandler() { - struct sigaction sa; - sa.sa_sigaction = SigprofHandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART | SA_SIGINFO; - if (sigaction(SIGPROF, &sa, 0) != 0) { - fprintf(stderr, "failed to install signal handler\n"); - abort(); - } -} - -int main() { - alarm(60); // Kill the test if it hangs. - - // Install the signal handler - InstallSignalHandler(); - - // Lock the futex at first so the other thread will wait for it. - mutex.lock(); - - // Create the thread to wait for the futex. - pthread_t thread; - pthread_create(&thread, NULL, Thread, NULL); - - // Just waiting a bit to make sure the thead is at the FUTEX_WAIT_PRIVATE - // syscall. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - // Send the signal to the other thread, which will send the futex wake - // syscall. - int r = pthread_kill(thread, SIGPROF); - assert(r == 0); - - // Futex should be notified and the thread should be able to continue. - pthread_join(thread, NULL); - - // Exiting successfully. - fprintf(stderr, "PASS\n"); - return 0; -} - -// CHECK-NOT: WARNING: ThreadSanitizer: -// CHECK: PASS -- cgit v1.1