forked from OSchip/llvm-project
tsan: implement suppressions for top frame only
The new suppression type is called "race_top" and is matched only against top frame in report stacks. This is required for situations when we want to suppress a race in a "thread pool" or "event loop" implementation. If we simply use "race:ThreadPool::Execute" suppression, that can suppress everything in the program. Reviewed in http://reviews.llvm.org/D10686 llvm-svn: 240949
This commit is contained in:
parent
0fc26d21bd
commit
ffb551b2b0
|
@ -44,8 +44,9 @@ namespace __tsan {
|
|||
ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
|
||||
static SuppressionContext *suppression_ctx = nullptr;
|
||||
static const char *kSuppressionTypes[] = {
|
||||
kSuppressionRace, kSuppressionMutex, kSuppressionThread,
|
||||
kSuppressionSignal, kSuppressionLib, kSuppressionDeadlock};
|
||||
kSuppressionRace, kSuppressionRaceTop, kSuppressionMutex,
|
||||
kSuppressionThread, kSuppressionSignal, kSuppressionLib,
|
||||
kSuppressionDeadlock};
|
||||
|
||||
void InitializeSuppressions() {
|
||||
CHECK_EQ(nullptr, suppression_ctx);
|
||||
|
@ -94,6 +95,18 @@ static const char *conv(ReportType typ) {
|
|||
Die();
|
||||
}
|
||||
|
||||
static uptr IsSuppressed(const char *stype, const AddressInfo &info,
|
||||
Suppression **sp) {
|
||||
if (suppression_ctx->Match(info.function, stype, sp) ||
|
||||
suppression_ctx->Match(info.file, stype, sp) ||
|
||||
suppression_ctx->Match(info.module, stype, sp)) {
|
||||
DPrintf("ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
|
||||
(*sp)->hit_count++;
|
||||
return info.address;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
|
||||
CHECK(suppression_ctx);
|
||||
if (!suppression_ctx->SuppressionCount() || stack == 0 ||
|
||||
|
@ -102,19 +115,14 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
|
|||
const char *stype = conv(typ);
|
||||
if (0 == internal_strcmp(stype, kSuppressionNone))
|
||||
return 0;
|
||||
Suppression *s;
|
||||
for (const SymbolizedStack *frame = stack->frames; frame;
|
||||
frame = frame->next) {
|
||||
const AddressInfo &info = frame->info;
|
||||
if (suppression_ctx->Match(info.function, stype, &s) ||
|
||||
suppression_ctx->Match(info.file, stype, &s) ||
|
||||
suppression_ctx->Match(info.module, stype, &s)) {
|
||||
DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
|
||||
s->hit_count++;
|
||||
*sp = s;
|
||||
return info.address;
|
||||
}
|
||||
frame = frame->next) {
|
||||
uptr pc = IsSuppressed(stype, frame->info, sp);
|
||||
if (pc != 0)
|
||||
return pc;
|
||||
}
|
||||
if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
|
||||
return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace __tsan {
|
|||
|
||||
const char kSuppressionNone[] = "none";
|
||||
const char kSuppressionRace[] = "race";
|
||||
const char kSuppressionRaceTop[] = "race_top";
|
||||
const char kSuppressionMutex[] = "mutex";
|
||||
const char kSuppressionThread[] = "thread";
|
||||
const char kSuppressionSignal[] = "signal";
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// RUN: echo "race_top:TopFunction" > %t.supp
|
||||
// RUN: %clangxx_tsan -O1 %s -o %t
|
||||
// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%t.supp'" %run %t 2>&1 | FileCheck %s
|
||||
// RUN: rm %t.supp
|
||||
#include "test.h"
|
||||
|
||||
int Global;
|
||||
|
||||
void TopFunction(int *p) {
|
||||
*p = 1;
|
||||
}
|
||||
|
||||
void *Thread(void *x) {
|
||||
barrier_wait(&barrier);
|
||||
TopFunction(&Global);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
barrier_init(&barrier, 2);
|
||||
pthread_t t;
|
||||
pthread_create(&t, 0, Thread, 0);
|
||||
Global--;
|
||||
barrier_wait(&barrier);
|
||||
pthread_join(t, 0);
|
||||
fprintf(stderr, "DONE\n");
|
||||
}
|
||||
|
||||
// CHECK-NOT: WARNING: ThreadSanitizer: data race
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: echo "race_top:TopFunction" > %t.supp
|
||||
// RUN: %clangxx_tsan -O1 %s -o %t
|
||||
// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%t.supp'" %deflake %run %t 2>&1 | FileCheck %s
|
||||
// RUN: rm %t.supp
|
||||
#include "test.h"
|
||||
|
||||
int Global;
|
||||
|
||||
void AnotherFunction(int *p) {
|
||||
*p = 1;
|
||||
}
|
||||
|
||||
void TopFunction(int *p) {
|
||||
AnotherFunction(p);
|
||||
}
|
||||
|
||||
void *Thread(void *x) {
|
||||
barrier_wait(&barrier);
|
||||
TopFunction(&Global);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
barrier_init(&barrier, 2);
|
||||
pthread_t t;
|
||||
pthread_create(&t, 0, Thread, 0);
|
||||
Global--;
|
||||
barrier_wait(&barrier);
|
||||
pthread_join(t, 0);
|
||||
}
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: data race
|
Loading…
Reference in New Issue