summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2012-08-31 17:27:49 +0000
committerDmitry Vyukov <dvyukov@google.com>2012-08-31 17:27:49 +0000
commit848531192777acecf79747dc7c1ffeedf5c1da9f (patch)
tree557b970b78bf62eb5d431982a285ef7ebf36be69 /lib/tsan/rtl
parent1b1de03d493b5d4950988924ee4ad900b6c78008 (diff)
downloadcompiler-rt-848531192777acecf79747dc7c1ffeedf5c1da9f.tar.gz
tsan: add "as if synchronized via sleep" feature
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@163006 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/rtl')
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc27
-rw-r--r--lib/tsan/rtl/tsan_mman.cc6
-rw-r--r--lib/tsan/rtl/tsan_report.cc11
-rw-r--r--lib/tsan/rtl/tsan_report.h1
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc15
-rw-r--r--lib/tsan/rtl/tsan_rtl.h9
-rw-r--r--lib/tsan/rtl/tsan_rtl_mutex.cc17
-rw-r--r--lib/tsan/rtl/tsan_rtl_report.cc18
-rw-r--r--lib/tsan/rtl/tsan_stat.h3
9 files changed, 99 insertions, 8 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 1dce12bca..f0a46ac61 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -51,7 +51,6 @@ extern "C" void *pthread_self();
extern "C" void _exit(int status);
extern "C" int __cxa_atexit(void (*func)(void *arg), void *arg, void *dso);
extern "C" int *__errno_location();
-extern "C" int usleep(unsigned usec);
const int PTHREAD_MUTEX_RECURSIVE = 1;
const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
const int kPthreadAttrSize = 56;
@@ -213,6 +212,27 @@ static void invoke_free_hook(void *ptr) {
__tsan_free_hook(ptr);
}
+TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
+ SCOPED_TSAN_INTERCEPTOR(sleep, sec);
+ unsigned res = sleep(sec);
+ AfterSleep(thr, pc);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, usleep, long_t usec) {
+ SCOPED_TSAN_INTERCEPTOR(usleep, usec);
+ int res = usleep(usec);
+ AfterSleep(thr, pc);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
+ SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
+ int res = nanosleep(req, rem);
+ AfterSleep(thr, pc);
+ return res;
+}
+
class AtExitContext {
public:
AtExitContext()
@@ -269,7 +289,7 @@ static void finalize(void *arg) {
{
ScopedInRtl in_rtl;
DestroyAndFree(atexit_ctx);
- usleep(flags()->atexit_sleep_ms * 1000);
+ REAL(usleep)(flags()->atexit_sleep_ms * 1000);
}
int status = Finalize(cur_thread());
if (status)
@@ -1572,6 +1592,9 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(raise);
TSAN_INTERCEPT(kill);
TSAN_INTERCEPT(pthread_kill);
+ TSAN_INTERCEPT(sleep);
+ TSAN_INTERCEPT(usleep);
+ TSAN_INTERCEPT(nanosleep);
atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
AtExitContext();
diff --git a/lib/tsan/rtl/tsan_mman.cc b/lib/tsan/rtl/tsan_mman.cc
index ba8972f4c..1e1022bcd 100644
--- a/lib/tsan/rtl/tsan_mman.cc
+++ b/lib/tsan/rtl/tsan_mman.cc
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
-#include "sanitizer_common/sanitizer_stackdepot.h"
#include "tsan_mman.h"
#include "tsan_rtl.h"
#include "tsan_report.h"
@@ -51,10 +50,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
b->size = sz;
b->alloc_tid = thr->unique_id;
- b->alloc_stack_id = 0;
- if (thr->shadow_stack_pos) // May happen during bootstrap.
- b->alloc_stack_id = StackDepotPut(thr->shadow_stack,
- thr->shadow_stack_pos - thr->shadow_stack);
+ b->alloc_stack_id = CurrentStackId(thr, pc);
if (CTX() && CTX()->initialized) {
MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
}
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 6ce164bcf..c95ca8f20 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -21,7 +21,8 @@ ReportDesc::ReportDesc()
, mops(MBlockReportMop)
, locs(MBlockReportLoc)
, mutexes(MBlockReportMutex)
- , threads(MBlockReportThread) {
+ , threads(MBlockReportThread)
+ , sleep() {
}
ReportDesc::~ReportDesc() {
@@ -110,6 +111,11 @@ static void PrintThread(const ReportThread *rt) {
PrintStack(rt->stack);
}
+static void PrintSleep(const ReportStack *s) {
+ TsanPrintf(" As if synchronized via sleep:\n");
+ PrintStack(s);
+}
+
void PrintReport(const ReportDesc *rep) {
TsanPrintf("==================\n");
PrintHeader(rep->typ);
@@ -123,6 +129,9 @@ void PrintReport(const ReportDesc *rep) {
for (uptr i = 0; i < rep->mops.Size(); i++)
PrintMop(rep->mops[i], i == 0);
+ if (rep->sleep)
+ PrintSleep(rep->sleep);
+
for (uptr i = 0; i < rep->locs.Size(); i++)
PrintLocation(rep->locs[i]);
diff --git a/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h
index d139296d5..a447d56b6 100644
--- a/lib/tsan/rtl/tsan_report.h
+++ b/lib/tsan/rtl/tsan_report.h
@@ -85,6 +85,7 @@ class ReportDesc {
Vector<ReportLocation*> locs;
Vector<ReportMutex*> mutexes;
Vector<ReportThread*> threads;
+ ReportStack *sleep;
ReportDesc();
~ReportDesc();
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index 9ca295da8..962c07a5b 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -15,6 +15,7 @@
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "tsan_defs.h"
#include "tsan_platform.h"
@@ -223,6 +224,20 @@ int Finalize(ThreadState *thr) {
return failed ? flags()->exitcode : 0;
}
+u32 CurrentStackId(ThreadState *thr, uptr pc) {
+ if (thr->shadow_stack_pos == 0) // May happen during bootstrap.
+ return 0;
+ if (pc) {
+ thr->shadow_stack_pos[0] = pc;
+ thr->shadow_stack_pos++;
+ }
+ u32 id = StackDepotPut(thr->shadow_stack,
+ thr->shadow_stack_pos - thr->shadow_stack);
+ if (pc)
+ thr->shadow_stack_pos--;
+ return id;
+}
+
void TraceSwitch(ThreadState *thr) {
thr->nomalloc++;
ScopedInRtl in_rtl;
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index bc621cd30..d79af1e5c 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -286,6 +286,11 @@ struct ThreadState {
bool in_signal_handler;
SignalContext *signal_ctx;
+#ifndef TSAN_GO
+ u32 last_sleep_stack_id;
+ ThreadClock last_sleep_clock;
+#endif
+
// Set in regions of runtime that must be signal-safe and fork-safe.
// If set, malloc must not be called.
int nomalloc;
@@ -405,6 +410,7 @@ class ScopedReport {
void AddThread(const ThreadContext *tctx);
void AddMutex(const SyncVar *s);
void AddLocation(uptr addr, uptr size);
+ void AddSleep(u32 stack_id);
const ReportDesc *GetReport() const;
@@ -446,6 +452,8 @@ bool IsExpectedReport(uptr addr, uptr size);
# define DPrintf2(...)
#endif
+u32 CurrentStackId(ThreadState *thr, uptr pc);
+
void Initialize(ThreadState *thr);
int Finalize(ThreadState *thr);
@@ -489,6 +497,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
void Acquire(ThreadState *thr, uptr pc, uptr addr);
void Release(ThreadState *thr, uptr pc, uptr addr);
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
+void AfterSleep(ThreadState *thr, uptr pc);
// The hacky call uses custom calling convention and an assembly thunk.
// It is considerably faster that a normal call for the caller
diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc
index 167541f0f..a743924db 100644
--- a/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -230,4 +230,21 @@ void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
s->mtx.Unlock();
}
+#ifndef TSAN_GO
+void AfterSleep(ThreadState *thr, uptr pc) {
+ Context *ctx = CTX();
+ thr->last_sleep_stack_id = CurrentStackId(thr, pc);
+ Lock l(&ctx->thread_mtx);
+ for (unsigned i = 0; i < kMaxTid; i++) {
+ ThreadContext *tctx = ctx->threads[i];
+ if (tctx == 0)
+ continue;
+ if (tctx->status == ThreadStatusRunning)
+ thr->last_sleep_clock.set(i, tctx->thr->fast_state.epoch());
+ else
+ thr->last_sleep_clock.set(i, tctx->epoch1);
+ }
+}
+#endif
+
} // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index a32d30a1b..8173700d0 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -230,6 +230,16 @@ void ScopedReport::AddLocation(uptr addr, uptr size) {
}
}
+void ScopedReport::AddSleep(u32 stack_id) {
+ uptr ssz = 0;
+ const uptr *stack = StackDepotGet(stack_id, &ssz);
+ if (stack) {
+ StackTrace trace;
+ trace.Init(stack, ssz);
+ rep_->sleep = SymbolizeStack(trace);
+ }
+}
+
const ReportDesc *ScopedReport::GetReport() const {
return rep_;
}
@@ -411,6 +421,14 @@ void ReportRace(ThreadState *thr) {
rep.AddLocation(addr_min, addr_max - addr_min);
+#ifndef TSAN_GO
+ { // NOLINT
+ Shadow s(thr->racy_state[1]);
+ if (s.epoch() <= thr->last_sleep_clock.get(s.tid()))
+ rep.AddSleep(thr->last_sleep_stack_id);
+ }
+#endif
+
if (!OutputReport(rep, rep.GetReport()->mops[0]->stack))
return;
diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h
index 6bc5d230f..d99491f74 100644
--- a/lib/tsan/rtl/tsan_stat.h
+++ b/lib/tsan/rtl/tsan_stat.h
@@ -199,6 +199,9 @@ enum StatType {
StatInt_raise,
StatInt_kill,
StatInt_pthread_kill,
+ StatInt_sleep,
+ StatInt_usleep,
+ StatInt_nanosleep,
// Dynamic annotations.
StatAnnotation,