103 lines · cpp
1// This run stresses global reset happenning concurrently with everything else.2// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=flush_memory_ms=1:flush_symbolizer_ms=1:memory_limit_mb=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NORACE3// This run stresses race reporting happenning concurrently with everything else.4// RUN: %clangxx_tsan -O1 %s -DRACE=1 -o %t && %env_tsan_opts=suppress_equal_stacks=0 %deflake %run %t | FileCheck %s --check-prefix=CHECK-RACE5#include "test.h"6#include <fcntl.h>7#include <string.h>8 9volatile long stop;10long atomic, read_only, racy;11int fds[2];12 13__attribute__((noinline)) void *SecondaryThread(void *x) {14 __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);15 return NULL;16}17 18void *Thread(void *x) {19 const int me = (long)x;20 volatile long sink = 0;21 int fd = -1;22 while (!stop) {23 // If me == 0, we do all of the following,24 // otherwise only 1 type of action.25 if (me == 0 || me == 1) {26 // just read the stop variable27 }28 if (me == 0 || me == 2) {29 __atomic_store_n(&atomic, sink, __ATOMIC_RELEASE);30 }31 if (me == 0 || me == 3) {32 sink += __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);33 }34 if (me == 0 || me == 4) {35 SecondaryThread(NULL);36 }37 if (me == 0 || me == 5) {38 write(fds[1], fds, 1);39 }40 if (me == 0 || me == 6) {41 char buf[2];42 read(fds[0], &buf, sizeof(buf));43 }44 if (me == 0 || me == 7) {45 pthread_t th;46 pthread_create(&th, NULL, SecondaryThread, NULL);47 pthread_join(th, NULL);48 }49 if (me == 0 || me == 8) {50 long buf;51 memcpy(&buf, &read_only, sizeof(buf));52 sink += buf;53 }54 if (me == 0 || me == 9) {55#if RACE56 sink += racy++;57#else58 sink += racy;59#endif60 }61 if (me == 0 || me == 10) {62 fd = open("/dev/null", O_RDONLY);63 if (fd != -1) {64 close(fd);65 fd = -1;66 }67 }68 // If you add more actions, update kActions in main.69 }70 return NULL;71}72 73int main() {74 ANNOTATE_BENIGN_RACE(stop);75 if (pipe(fds))76 exit((perror("pipe"), 1));77 if (fcntl(fds[0], F_SETFL, O_NONBLOCK))78 exit((perror("fcntl"), 1));79 if (fcntl(fds[1], F_SETFL, O_NONBLOCK))80 exit((perror("fcntl"), 1));81 const int kActions = 11;82#if RACE83 const int kMultiplier = 1;84#else85 const int kMultiplier = 4;86#endif87 pthread_t t[kActions * kMultiplier];88 for (int i = 0; i < kActions * kMultiplier; i++)89 pthread_create(&t[i], NULL, Thread, (void *)(long)(i % kActions));90 sleep(5);91 stop = 1;92 for (int i = 0; i < kActions * kMultiplier; i++)93 pthread_join(t[i], NULL);94 fprintf(stderr, "DONE\n");95 return 0;96}97 98// CHECK-NORACE-NOT: ThreadSanitizer:99// CHECK-NORACE: DONE100// CHECK-NORACE-NOT: ThreadSanitizer:101// CHECK-RACE: ThreadSanitizer: data race102// CHECK-RACE: DONE103