forked from OSchip/llvm-project
parent
6c7dbf5858
commit
5bfac97ff9
|
|
@ -28,9 +28,7 @@ const int kTidBits = 13;
|
||||||
const unsigned kMaxTid = 1 << kTidBits;
|
const unsigned kMaxTid = 1 << kTidBits;
|
||||||
const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
|
const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
|
||||||
const int kClkBits = 43;
|
const int kClkBits = 43;
|
||||||
#ifdef TSAN_GO
|
#ifndef TSAN_GO
|
||||||
const int kShadowStackSize = 8 * 1024;
|
|
||||||
#else
|
|
||||||
const int kShadowStackSize = 1024;
|
const int kShadowStackSize = 1024;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ enum MBlockType {
|
||||||
MBlockScopedBuf,
|
MBlockScopedBuf,
|
||||||
MBlockString,
|
MBlockString,
|
||||||
MBlockStackTrace,
|
MBlockStackTrace,
|
||||||
|
MBlockShadowStack,
|
||||||
MBlockSync,
|
MBlockSync,
|
||||||
MBlockClock,
|
MBlockClock,
|
||||||
MBlockThreadContex,
|
MBlockThreadContex,
|
||||||
|
|
|
||||||
|
|
@ -451,14 +451,28 @@ void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
|
||||||
void FuncEntry(ThreadState *thr, uptr pc) {
|
void FuncEntry(ThreadState *thr, uptr pc) {
|
||||||
DCHECK_EQ(thr->in_rtl, 0);
|
DCHECK_EQ(thr->in_rtl, 0);
|
||||||
StatInc(thr, StatFuncEnter);
|
StatInc(thr, StatFuncEnter);
|
||||||
DPrintf2("#%d: tsan::FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
|
DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
|
||||||
thr->fast_state.IncrementEpoch();
|
thr->fast_state.IncrementEpoch();
|
||||||
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncEnter, pc);
|
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncEnter, pc);
|
||||||
|
|
||||||
// Shadow stack maintenance can be replaced with
|
// Shadow stack maintenance can be replaced with
|
||||||
// stack unwinding during trace switch (which presumably must be faster).
|
// stack unwinding during trace switch (which presumably must be faster).
|
||||||
DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]);
|
DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]);
|
||||||
|
#ifndef TSAN_GO
|
||||||
DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
|
DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
|
||||||
|
#else
|
||||||
|
if (thr->shadow_stack_pos == thr->shadow_stack_end) {
|
||||||
|
const int sz = thr->shadow_stack_end - thr->shadow_stack;
|
||||||
|
const int newsz = 2 * sz;
|
||||||
|
uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
|
||||||
|
newsz * sizeof(uptr));
|
||||||
|
internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
|
||||||
|
internal_free(thr->shadow_stack);
|
||||||
|
thr->shadow_stack = newstack;
|
||||||
|
thr->shadow_stack_pos = newstack + sz;
|
||||||
|
thr->shadow_stack_end = newstack + newsz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
thr->shadow_stack_pos[0] = pc;
|
thr->shadow_stack_pos[0] = pc;
|
||||||
thr->shadow_stack_pos++;
|
thr->shadow_stack_pos++;
|
||||||
}
|
}
|
||||||
|
|
@ -466,12 +480,14 @@ void FuncEntry(ThreadState *thr, uptr pc) {
|
||||||
void FuncExit(ThreadState *thr) {
|
void FuncExit(ThreadState *thr) {
|
||||||
DCHECK_EQ(thr->in_rtl, 0);
|
DCHECK_EQ(thr->in_rtl, 0);
|
||||||
StatInc(thr, StatFuncExit);
|
StatInc(thr, StatFuncExit);
|
||||||
DPrintf2("#%d: tsan::FuncExit\n", (int)thr->fast_state.tid());
|
DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
|
||||||
thr->fast_state.IncrementEpoch();
|
thr->fast_state.IncrementEpoch();
|
||||||
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncExit, 0);
|
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncExit, 0);
|
||||||
|
|
||||||
DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]);
|
DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]);
|
||||||
|
#ifndef TSAN_GO
|
||||||
DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
|
DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
|
||||||
|
#endif
|
||||||
thr->shadow_stack_pos--;
|
thr->shadow_stack_pos--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,14 @@ struct ThreadState {
|
||||||
u64 *racy_shadow_addr;
|
u64 *racy_shadow_addr;
|
||||||
u64 racy_state[2];
|
u64 racy_state[2];
|
||||||
Trace trace;
|
Trace trace;
|
||||||
|
#ifndef TSAN_GO
|
||||||
|
// C/C++ uses embed shadow stack of fixed size.
|
||||||
uptr shadow_stack[kShadowStackSize];
|
uptr shadow_stack[kShadowStackSize];
|
||||||
|
#else
|
||||||
|
// Go uses satellite shadow stack with dynamic size.
|
||||||
|
uptr *shadow_stack;
|
||||||
|
uptr *shadow_stack_end;
|
||||||
|
#endif
|
||||||
ThreadClock clock;
|
ThreadClock clock;
|
||||||
u64 stat[StatCnt];
|
u64 stat[StatCnt];
|
||||||
const int tid;
|
const int tid;
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,14 @@ void ThreadStart(ThreadState *thr, int tid) {
|
||||||
tctx->epoch1 = (u64)-1;
|
tctx->epoch1 = (u64)-1;
|
||||||
new(thr) ThreadState(CTX(), tid, tctx->epoch0, stk_addr, stk_size,
|
new(thr) ThreadState(CTX(), tid, tctx->epoch0, stk_addr, stk_size,
|
||||||
tls_addr, tls_size);
|
tls_addr, tls_size);
|
||||||
|
#ifdef TSAN_GO
|
||||||
|
// Setup dynamic shadow stack.
|
||||||
|
const int kInitStackSize = 8;
|
||||||
|
thr->shadow_stack = (uptr*)internal_alloc(MBlockShadowStack,
|
||||||
|
kInitStackSize * sizeof(uptr));
|
||||||
|
thr->shadow_stack_pos = thr->shadow_stack;
|
||||||
|
thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
|
||||||
|
#endif
|
||||||
tctx->thr = thr;
|
tctx->thr = thr;
|
||||||
thr->fast_synch_epoch = tctx->epoch0;
|
thr->fast_synch_epoch = tctx->epoch0;
|
||||||
thr->clock.set(tid, tctx->epoch0);
|
thr->clock.set(tid, tctx->epoch0);
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ void StackTrace::Init(const uptr *pcs, uptr cnt) {
|
||||||
|
|
||||||
void StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) {
|
void StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) {
|
||||||
Reset();
|
Reset();
|
||||||
n_ = thr->shadow_stack_pos - &thr->shadow_stack[0];
|
n_ = thr->shadow_stack_pos - thr->shadow_stack;
|
||||||
if (n_ + !!toppc == 0)
|
if (n_ + !!toppc == 0)
|
||||||
return;
|
return;
|
||||||
if (c_) {
|
if (c_) {
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,16 @@ typedef u64 Event;
|
||||||
struct TraceHeader {
|
struct TraceHeader {
|
||||||
StackTrace stack0; // Start stack for the trace.
|
StackTrace stack0; // Start stack for the trace.
|
||||||
u64 epoch0; // Start epoch for the trace.
|
u64 epoch0; // Start epoch for the trace.
|
||||||
|
#ifndef TSAN_GO
|
||||||
uptr stack0buf[kShadowStackSize];
|
uptr stack0buf[kShadowStackSize];
|
||||||
|
#endif
|
||||||
|
|
||||||
TraceHeader()
|
TraceHeader()
|
||||||
|
#ifndef TSAN_GO
|
||||||
: stack0(stack0buf, kShadowStackSize)
|
: stack0(stack0buf, kShadowStackSize)
|
||||||
|
#else
|
||||||
|
: stack0()
|
||||||
|
#endif
|
||||||
, epoch0() {
|
, epoch0() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue