[TSan] Use common flags in the same way as all the other sanitizers

llvm-svn: 217559
This commit is contained in:
Alexey Samsonov 2014-09-10 23:08:06 +00:00
parent 611c906cb3
commit 5c825967ea
8 changed files with 37 additions and 116 deletions

View File

@ -93,21 +93,19 @@ void InitializeFlags(Flags *f, const char *env) {
// DDFlags // DDFlags
f->second_deadlock_stack = false; f->second_deadlock_stack = false;
SetCommonFlagsDefaults(f); CommonFlags *cf = common_flags();
SetCommonFlagsDefaults(cf);
// Override some common flags defaults. // Override some common flags defaults.
f->allow_addr2line = true; cf->allow_addr2line = true;
f->detect_deadlocks = true; cf->detect_deadlocks = true;
f->print_suppressions = false; cf->print_suppressions = false;
// Let a frontend override. // Let a frontend override.
ParseFlags(f, __tsan_default_options()); ParseFlags(f, __tsan_default_options());
ParseCommonFlagsFromString(f, __tsan_default_options()); ParseCommonFlagsFromString(cf, __tsan_default_options());
// Override from command line. // Override from command line.
ParseFlags(f, env); ParseFlags(f, env);
ParseCommonFlagsFromString(f, env); ParseCommonFlagsFromString(cf, env);
// Copy back to common flags.
internal_memcpy(common_flags(), f, sizeof(*common_flags()));
// Sanity check. // Sanity check.
if (!f->report_bugs) { if (!f->report_bugs) {
@ -116,7 +114,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->report_signal_unsafe = false; f->report_signal_unsafe = false;
} }
if (f->help) PrintFlagDescriptions(); if (cf->help) PrintFlagDescriptions();
if (f->history_size < 0 || f->history_size > 7) { if (f->history_size < 0 || f->history_size > 7) {
Printf("ThreadSanitizer: incorrect value for history_size" Printf("ThreadSanitizer: incorrect value for history_size"

View File

@ -19,7 +19,7 @@
namespace __tsan { namespace __tsan {
struct Flags : CommonFlags, DDFlags { struct Flags : DDFlags {
// Enable dynamic annotations, otherwise they are no-ops. // Enable dynamic annotations, otherwise they are no-ops.
bool enable_annotations; bool enable_annotations;
// Suppress a race report if we've already output another race report // Suppress a race report if we've already output another race report

View File

@ -167,8 +167,7 @@ static void BackgroundThread(void *arg) {
// Flush memory if requested. // Flush memory if requested.
if (flags()->flush_memory_ms > 0) { if (flags()->flush_memory_ms > 0) {
if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) { if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
if (flags()->verbosity > 0) VPrintf(1, "ThreadSanitizer: periodic memory flush\n");
Printf("ThreadSanitizer: periodic memory flush\n");
FlushShadowMemory(); FlushShadowMemory();
last_flush = NanoTime(); last_flush = NanoTime();
} }
@ -177,18 +176,14 @@ static void BackgroundThread(void *arg) {
if (flags()->memory_limit_mb > 0) { if (flags()->memory_limit_mb > 0) {
uptr rss = GetRSS(); uptr rss = GetRSS();
uptr limit = uptr(flags()->memory_limit_mb) << 20; uptr limit = uptr(flags()->memory_limit_mb) << 20;
if (flags()->verbosity > 0) { VPrintf(1, "ThreadSanitizer: memory flush check"
Printf("ThreadSanitizer: memory flush check" " RSS=%llu LAST=%llu LIMIT=%llu\n",
" RSS=%llu LAST=%llu LIMIT=%llu\n", (u64)rss >> 20, (u64)last_rss >> 20, (u64)limit >> 20);
(u64)rss>>20, (u64)last_rss>>20, (u64)limit>>20);
}
if (2 * rss > limit + last_rss) { if (2 * rss > limit + last_rss) {
if (flags()->verbosity > 0) VPrintf(1, "ThreadSanitizer: flushing memory due to RSS\n");
Printf("ThreadSanitizer: flushing memory due to RSS\n");
FlushShadowMemory(); FlushShadowMemory();
rss = GetRSS(); rss = GetRSS();
if (flags()->verbosity > 0) VPrintf(1, "ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
Printf("ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
} }
last_rss = rss; last_rss = rss;
} }
@ -303,7 +298,7 @@ void Initialize(ThreadState *thr) {
InitializeShadowMemory(); InitializeShadowMemory();
#endif #endif
// Setup correct file descriptor for error reports. // Setup correct file descriptor for error reports.
__sanitizer_set_report_path(flags()->log_path); __sanitizer_set_report_path(common_flags()->log_path);
InitializeSuppressions(); InitializeSuppressions();
#ifndef TSAN_GO #ifndef TSAN_GO
InitializeLibIgnore(); InitializeLibIgnore();
@ -313,12 +308,11 @@ void Initialize(ThreadState *thr) {
#ifndef TSAN_GO #ifndef TSAN_GO
SetSandboxingCallback(StopBackgroundThread); SetSandboxingCallback(StopBackgroundThread);
#endif #endif
if (flags()->detect_deadlocks) if (common_flags()->detect_deadlocks)
ctx->dd = DDetector::Create(flags()); ctx->dd = DDetector::Create(flags());
if (ctx->flags.verbosity) VPrintf(1, "***** Running under ThreadSanitizer v2 (pid %d) *****\n",
Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n", (int)internal_getpid());
(int)internal_getpid());
// Initialize thread 0. // Initialize thread 0.
int tid = ThreadCreate(thr, 0, 0, true); int tid = ThreadCreate(thr, 0, 0, true);
@ -349,7 +343,7 @@ int Finalize(ThreadState *thr) {
ctx->report_mtx.Unlock(); ctx->report_mtx.Unlock();
#ifndef TSAN_GO #ifndef TSAN_GO
if (ctx->flags.verbosity) if (common_flags()->verbosity)
AllocatorPrintStats(); AllocatorPrintStats();
#endif #endif
@ -370,7 +364,7 @@ int Finalize(ThreadState *thr) {
ctx->nmissed_expected); ctx->nmissed_expected);
} }
if (flags()->print_suppressions) if (common_flags()->print_suppressions)
PrintMatchedSuppressions(); PrintMatchedSuppressions();
#ifndef TSAN_GO #ifndef TSAN_GO
if (flags()->print_benign) if (flags()->print_benign)

View File

@ -103,7 +103,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr); SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr);
if (s == 0) if (s == 0)
return; return;
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
Callback cb(thr, pc); Callback cb(thr, pc);
ctx->dd->MutexDestroy(&cb, &s->dd); ctx->dd->MutexDestroy(&cb, &s->dd);
ctx->dd->MutexInit(&cb, &s->dd); ctx->dd->MutexInit(&cb, &s->dd);
@ -172,7 +172,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) {
} }
s->recursion += rec; s->recursion += rec;
thr->mset.Add(s->GetId(), true, thr->fast_state.epoch()); thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
if (flags()->detect_deadlocks && (s->recursion - rec) == 0) { if (common_flags()->detect_deadlocks && (s->recursion - rec) == 0) {
Callback cb(thr, pc); Callback cb(thr, pc);
if (!try_lock) if (!try_lock)
ctx->dd->MutexBeforeLock(&cb, &s->dd, true); ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
@ -183,7 +183,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) {
// Can't touch s after this point. // Can't touch s after this point.
if (report_double_lock) if (report_double_lock)
ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid); ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid);
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
Callback cb(thr, pc); Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
} }
@ -215,7 +215,8 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
} }
} }
thr->mset.Del(s->GetId(), true); thr->mset.Del(s->GetId(), true);
if (flags()->detect_deadlocks && s->recursion == 0 && !report_bad_unlock) { if (common_flags()->detect_deadlocks && s->recursion == 0 &&
!report_bad_unlock) {
Callback cb(thr, pc); Callback cb(thr, pc);
ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true); ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
} }
@ -224,7 +225,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
// Can't touch s after this point. // Can't touch s after this point.
if (report_bad_unlock) if (report_bad_unlock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid); ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
if (flags()->detect_deadlocks && !report_bad_unlock) { if (common_flags()->detect_deadlocks && !report_bad_unlock) {
Callback cb(thr, pc); Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
} }
@ -249,7 +250,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool trylock) {
AcquireImpl(thr, pc, &s->clock); AcquireImpl(thr, pc, &s->clock);
s->last_lock = thr->fast_state.raw(); s->last_lock = thr->fast_state.raw();
thr->mset.Add(s->GetId(), false, thr->fast_state.epoch()); thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
if (flags()->detect_deadlocks && s->recursion == 0) { if (common_flags()->detect_deadlocks && s->recursion == 0) {
Callback cb(thr, pc); Callback cb(thr, pc);
if (!trylock) if (!trylock)
ctx->dd->MutexBeforeLock(&cb, &s->dd, false); ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
@ -260,7 +261,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool trylock) {
// Can't touch s after this point. // Can't touch s after this point.
if (report_bad_lock) if (report_bad_lock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid); ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid);
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
Callback cb(thr, pc); Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
} }
@ -282,7 +283,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
} }
} }
ReleaseImpl(thr, pc, &s->read_clock); ReleaseImpl(thr, pc, &s->read_clock);
if (flags()->detect_deadlocks && s->recursion == 0) { if (common_flags()->detect_deadlocks && s->recursion == 0) {
Callback cb(thr, pc); Callback cb(thr, pc);
ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false); ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
} }
@ -292,7 +293,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
thr->mset.Del(mid, false); thr->mset.Del(mid, false);
if (report_bad_unlock) if (report_bad_unlock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid); ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid);
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
Callback cb(thr, pc); Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
} }
@ -330,7 +331,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
report_bad_unlock = true; report_bad_unlock = true;
} }
thr->mset.Del(s->GetId(), write); thr->mset.Del(s->GetId(), write);
if (flags()->detect_deadlocks && s->recursion == 0) { if (common_flags()->detect_deadlocks && s->recursion == 0) {
Callback cb(thr, pc); Callback cb(thr, pc);
ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write); ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
} }
@ -339,7 +340,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
// Can't touch s after this point. // Can't touch s after this point.
if (report_bad_unlock) if (report_bad_unlock)
ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid); ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
Callback cb(thr, pc); Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
} }

View File

@ -61,7 +61,7 @@ static void StackStripMain(ReportStack *stack) {
ReportStack *last_frame2 = 0; ReportStack *last_frame2 = 0;
const char *prefix = "__interceptor_"; const char *prefix = "__interceptor_";
uptr prefix_len = internal_strlen(prefix); uptr prefix_len = internal_strlen(prefix);
const char *path_prefix = flags()->strip_path_prefix; const char *path_prefix = common_flags()->strip_path_prefix;
uptr path_prefix_len = internal_strlen(path_prefix); uptr path_prefix_len = internal_strlen(path_prefix);
char *pos; char *pos;
for (ReportStack *ent = stack; ent; ent = ent->next) { for (ReportStack *ent = stack; ent; ent = ent->next) {

View File

@ -107,7 +107,7 @@ void ThreadContext::OnStarted(void *arg) {
#ifndef TSAN_GO #ifndef TSAN_GO
AllocatorThreadStart(thr); AllocatorThreadStart(thr);
#endif #endif
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
thr->dd_pt = ctx->dd->CreatePhysicalThread(); thr->dd_pt = ctx->dd->CreatePhysicalThread();
thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id); thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id);
} }
@ -134,7 +134,7 @@ void ThreadContext::OnFinished() {
} }
epoch1 = thr->fast_state.epoch(); epoch1 = thr->fast_state.epoch();
if (flags()->detect_deadlocks) { if (common_flags()->detect_deadlocks) {
ctx->dd->DestroyPhysicalThread(thr->dd_pt); ctx->dd->DestroyPhysicalThread(thr->dd_pt);
ctx->dd->DestroyLogicalThread(thr->dd_lt); ctx->dd->DestroyLogicalThread(thr->dd_lt);
} }

View File

@ -32,7 +32,7 @@ void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) {
creation_stack_id = 0; creation_stack_id = 0;
if (kCppMode) // Go does not use them if (kCppMode) // Go does not use them
creation_stack_id = CurrentStackId(thr, pc); creation_stack_id = CurrentStackId(thr, pc);
if (flags()->detect_deadlocks) if (common_flags()->detect_deadlocks)
DDMutexInit(thr, pc, this); DDMutexInit(thr, pc, this);
} }

View File

@ -45,8 +45,6 @@ static const char *options1 =
" report_signal_unsafe=0" " report_signal_unsafe=0"
" report_atomic_races=0" " report_atomic_races=0"
" force_seq_cst_atomics=0" " force_seq_cst_atomics=0"
" suppressions=qwerty"
" print_suppressions=0"
" print_benign=0" " print_benign=0"
" exitcode=111" " exitcode=111"
" halt_on_error=0" " halt_on_error=0"
@ -60,22 +58,6 @@ static const char *options1 =
" history_size=5" " history_size=5"
" io_sync=1" " io_sync=1"
" die_after_fork=true" " die_after_fork=true"
" symbolize=0"
" external_symbolizer_path=asdfgh"
" allow_addr2line=true"
" strip_path_prefix=zxcvb"
" fast_unwind_on_fatal=0"
" fast_unwind_on_malloc=0"
" handle_ioctl=0"
" malloc_context_size=777"
" log_path=aaa"
" verbosity=2"
" detect_leaks=0"
" leak_check_at_exit=0"
" allocator_may_return_null=0"
" print_summary=0"
" legacy_pthread_cond=0"
""; "";
static const char *options2 = static const char *options2 =
@ -89,8 +71,6 @@ static const char *options2 =
" report_signal_unsafe=true" " report_signal_unsafe=true"
" report_atomic_races=true" " report_atomic_races=true"
" force_seq_cst_atomics=true" " force_seq_cst_atomics=true"
" suppressions=aaaaa"
" print_suppressions=true"
" print_benign=true" " print_benign=true"
" exitcode=222" " exitcode=222"
" halt_on_error=true" " halt_on_error=true"
@ -104,22 +84,6 @@ static const char *options2 =
" history_size=6" " history_size=6"
" io_sync=2" " io_sync=2"
" die_after_fork=false" " die_after_fork=false"
" symbolize=true"
" external_symbolizer_path=cccccc"
" allow_addr2line=false"
" strip_path_prefix=ddddddd"
" fast_unwind_on_fatal=true"
" fast_unwind_on_malloc=true"
" handle_ioctl=true"
" malloc_context_size=567"
" log_path=eeeeeee"
" verbosity=0"
" detect_leaks=true"
" leak_check_at_exit=true"
" allocator_may_return_null=true"
" print_summary=true"
" legacy_pthread_cond=true"
""; "";
void VerifyOptions1(Flags *f) { void VerifyOptions1(Flags *f) {
@ -133,8 +97,6 @@ void VerifyOptions1(Flags *f) {
EXPECT_EQ(f->report_signal_unsafe, 0); EXPECT_EQ(f->report_signal_unsafe, 0);
EXPECT_EQ(f->report_atomic_races, 0); EXPECT_EQ(f->report_atomic_races, 0);
EXPECT_EQ(f->force_seq_cst_atomics, 0); EXPECT_EQ(f->force_seq_cst_atomics, 0);
EXPECT_EQ(f->suppressions, std::string("qwerty"));
EXPECT_EQ(f->print_suppressions, 0);
EXPECT_EQ(f->print_benign, 0); EXPECT_EQ(f->print_benign, 0);
EXPECT_EQ(f->exitcode, 111); EXPECT_EQ(f->exitcode, 111);
EXPECT_EQ(f->halt_on_error, 0); EXPECT_EQ(f->halt_on_error, 0);
@ -148,22 +110,6 @@ void VerifyOptions1(Flags *f) {
EXPECT_EQ(f->history_size, 5); EXPECT_EQ(f->history_size, 5);
EXPECT_EQ(f->io_sync, 1); EXPECT_EQ(f->io_sync, 1);
EXPECT_EQ(f->die_after_fork, true); EXPECT_EQ(f->die_after_fork, true);
EXPECT_EQ(f->symbolize, 0);
EXPECT_EQ(f->external_symbolizer_path, std::string("asdfgh"));
EXPECT_EQ(f->allow_addr2line, true);
EXPECT_EQ(f->strip_path_prefix, std::string("zxcvb"));
EXPECT_EQ(f->fast_unwind_on_fatal, 0);
EXPECT_EQ(f->fast_unwind_on_malloc, 0);
EXPECT_EQ(f->handle_ioctl, 0);
EXPECT_EQ(f->malloc_context_size, 777);
EXPECT_EQ(f->log_path, std::string("aaa"));
EXPECT_EQ(f->verbosity, 2);
EXPECT_EQ(f->detect_leaks, 0);
EXPECT_EQ(f->leak_check_at_exit, 0);
EXPECT_EQ(f->allocator_may_return_null, 0);
EXPECT_EQ(f->print_summary, 0);
EXPECT_EQ(f->legacy_pthread_cond, false);
} }
void VerifyOptions2(Flags *f) { void VerifyOptions2(Flags *f) {
@ -177,8 +123,6 @@ void VerifyOptions2(Flags *f) {
EXPECT_EQ(f->report_signal_unsafe, true); EXPECT_EQ(f->report_signal_unsafe, true);
EXPECT_EQ(f->report_atomic_races, true); EXPECT_EQ(f->report_atomic_races, true);
EXPECT_EQ(f->force_seq_cst_atomics, true); EXPECT_EQ(f->force_seq_cst_atomics, true);
EXPECT_EQ(f->suppressions, std::string("aaaaa"));
EXPECT_EQ(f->print_suppressions, true);
EXPECT_EQ(f->print_benign, true); EXPECT_EQ(f->print_benign, true);
EXPECT_EQ(f->exitcode, 222); EXPECT_EQ(f->exitcode, 222);
EXPECT_EQ(f->halt_on_error, true); EXPECT_EQ(f->halt_on_error, true);
@ -192,22 +136,6 @@ void VerifyOptions2(Flags *f) {
EXPECT_EQ(f->history_size, 6); EXPECT_EQ(f->history_size, 6);
EXPECT_EQ(f->io_sync, 2); EXPECT_EQ(f->io_sync, 2);
EXPECT_EQ(f->die_after_fork, false); EXPECT_EQ(f->die_after_fork, false);
EXPECT_EQ(f->symbolize, true);
EXPECT_EQ(f->external_symbolizer_path, std::string("cccccc"));
EXPECT_EQ(f->allow_addr2line, false);
EXPECT_EQ(f->strip_path_prefix, std::string("ddddddd"));
EXPECT_EQ(f->fast_unwind_on_fatal, true);
EXPECT_EQ(f->fast_unwind_on_malloc, true);
EXPECT_EQ(f->handle_ioctl, true);
EXPECT_EQ(f->malloc_context_size, 567);
EXPECT_EQ(f->log_path, std::string("eeeeeee"));
EXPECT_EQ(f->verbosity, 0);
EXPECT_EQ(f->detect_leaks, true);
EXPECT_EQ(f->leak_check_at_exit, true);
EXPECT_EQ(f->allocator_may_return_null, true);
EXPECT_EQ(f->print_summary, true);
EXPECT_EQ(f->legacy_pthread_cond, true);
} }
static const char *test_default_options; static const char *test_default_options;