brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · 3c8804a Raw
114 lines · cpp
1// RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s2 3#include "../test.h"4#include <errno.h>5#include <linux/futex.h>6#include <pthread.h>7#include <signal.h>8#include <stdio.h>9#include <sys/syscall.h>10 11#include <cassert>12#include <stdexcept>13#include <thread>14 15#include <sanitizer/linux_syscall_hooks.h>16 17int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout,18          int *uaddr2, int val3) {19  __sanitizer_syscall_pre_futex(uaddr, futex_op, val, timeout, uaddr2, val3);20  int result = syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);21  __sanitizer_syscall_post_futex(result, uaddr, futex_op, val, timeout, uaddr2,22                                 val3);23  return result;24}25 26// Simple mutex implementation using futex.27class Mutex {28public:29  Mutex() : value(0) {}30 31  void lock() {32    int c;33    while ((c = __sync_val_compare_and_swap(&value, 0, 1)) != 0) {34      if (c != 1)35        continue;36      int r = futex(&value, FUTEX_WAIT_PRIVATE, 1, nullptr, nullptr, 0);37      if (r == -1 && errno != EAGAIN) {38        fprintf(stderr, "futex wait error\n");39        abort();40      }41    }42  }43 44  void unlock() {45    value = 0;46    int r = futex(&value, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);47    if (r == -1) {48      fprintf(stderr, "futex wake error\n");49      abort();50    }51  }52 53private:54  int value;55};56 57Mutex mutex;58 59void *Thread(void *x) {60  // Waiting for the futex.61  mutex.lock();62  // Finished waiting.63  return nullptr;64}65 66static void SigprofHandler(int signal, siginfo_t *info, void *context) {67  // Unlock the futex.68  mutex.unlock();69}70 71void InstallSignalHandler() {72  struct sigaction sa;73  sa.sa_sigaction = SigprofHandler;74  sigemptyset(&sa.sa_mask);75  sa.sa_flags = SA_RESTART | SA_SIGINFO;76  if (sigaction(SIGPROF, &sa, 0) != 0) {77    fprintf(stderr, "failed to install signal handler\n");78    abort();79  }80}81 82int main() {83  alarm(60); // Kill the test if it hangs.84 85  // Install the signal handler86  InstallSignalHandler();87 88  // Lock the futex at first so the other thread will wait for it.89  mutex.lock();90 91  // Create the thread to wait for the futex.92  pthread_t thread;93  pthread_create(&thread, NULL, Thread, NULL);94 95  // Just waiting a bit to make sure the thead is at the FUTEX_WAIT_PRIVATE96  // syscall.97  std::this_thread::sleep_for(std::chrono::milliseconds(100));98 99  // Send the signal to the other thread, which will send the futex wake100  // syscall.101  int r = pthread_kill(thread, SIGPROF);102  assert(r == 0);103 104  // Futex should be notified and the thread should be able to continue.105  pthread_join(thread, NULL);106 107  // Exiting successfully.108  fprintf(stderr, "PASS\n");109  return 0;110}111 112// CHECK-NOT: WARNING: ThreadSanitizer:113// CHECK: PASS114