Dmitry Vyukov 7505cc301f tsan: remove tracking of racy addresses
We used to deduplicate based on the race address to prevent lots
of repeated reports about the same race.

But now we clear the shadow for the racy address in DoReportRace:

  // This prevents trapping on this address in future.
  for (uptr i = 0; i < kShadowCnt; i++)
    StoreShadow(&shadow_mem[i], i == 0 ? Shadow::kRodata : Shadow::kEmpty);

It should have the same effect of not reporting duplicates
(and actually better because it's automatically reset when the memory is reallocated).

So drop the address deduplication code. Both simpler and faster.

Reviewed By: melver

Differential Revision: https://reviews.llvm.org/D130240
2022-07-25 10:33:26 +02:00

103 lines
2.7 KiB
C++

// This run stresses global reset happenning concurrently with everything else.
// 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-NORACE
// This run stresses race reporting happenning concurrently with everything else.
// RUN: %clangxx_tsan -O1 %s -DRACE=1 -o %t && %env_tsan_opts=suppress_equal_stacks=0 %deflake %run %t | FileCheck %s --check-prefix=CHECK-RACE
#include "test.h"
#include <fcntl.h>
#include <string.h>
volatile long stop;
long atomic, read_only, racy;
int fds[2];
__attribute__((noinline)) void *SecondaryThread(void *x) {
__atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
return NULL;
}
void *Thread(void *x) {
const int me = (long)x;
volatile long sink = 0;
int fd = -1;
while (!stop) {
// If me == 0, we do all of the following,
// otherwise only 1 type of action.
if (me == 0 || me == 1) {
// just read the stop variable
}
if (me == 0 || me == 2) {
__atomic_store_n(&atomic, sink, __ATOMIC_RELEASE);
}
if (me == 0 || me == 3) {
sink += __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
}
if (me == 0 || me == 4) {
SecondaryThread(NULL);
}
if (me == 0 || me == 5) {
write(fds[1], fds, 1);
}
if (me == 0 || me == 6) {
char buf[2];
read(fds[0], &buf, sizeof(buf));
}
if (me == 0 || me == 7) {
pthread_t th;
pthread_create(&th, NULL, SecondaryThread, NULL);
pthread_join(th, NULL);
}
if (me == 0 || me == 8) {
long buf;
memcpy(&buf, &read_only, sizeof(buf));
sink += buf;
}
if (me == 0 || me == 9) {
#if RACE
sink += racy++;
#else
sink += racy;
#endif
}
if (me == 0 || me == 10) {
fd = open("/dev/null", O_RDONLY);
if (fd != -1) {
close(fd);
fd = -1;
}
}
// If you add more actions, update kActions in main.
}
return NULL;
}
int main() {
ANNOTATE_BENIGN_RACE(stop);
if (pipe(fds))
exit((perror("pipe"), 1));
if (fcntl(fds[0], F_SETFL, O_NONBLOCK))
exit((perror("fcntl"), 1));
if (fcntl(fds[1], F_SETFL, O_NONBLOCK))
exit((perror("fcntl"), 1));
const int kActions = 11;
#if RACE
const int kMultiplier = 1;
#else
const int kMultiplier = 4;
#endif
pthread_t t[kActions * kMultiplier];
for (int i = 0; i < kActions * kMultiplier; i++)
pthread_create(&t[i], NULL, Thread, (void *)(long)(i % kActions));
sleep(5);
stop = 1;
for (int i = 0; i < kActions * kMultiplier; i++)
pthread_join(t[i], NULL);
fprintf(stderr, "DONE\n");
return 0;
}
// CHECK-NORACE-NOT: ThreadSanitizer:
// CHECK-NORACE: DONE
// CHECK-NORACE-NOT: ThreadSanitizer:
// CHECK-RACE: ThreadSanitizer: data race
// CHECK-RACE: DONE