tsan: introduce Tid and StackID typedefs

Currently we inconsistently use u32 and int for thread ids,
there are also "unique tid" and "os tid" and just lots of other
things identified by integers.
Additionally new tsan runtime will introduce yet another
thread identifier that is very different from current tids.
Similarly for stack IDs, it's easy to confuse u32 with other
integer identifiers. And when a function accepts u32 or a struct
contains u32 field, it's not always clear what it is.

Add Tid and StackID typedefs to make it clear what is what.

Reviewed By: melver

Differential Revision: https://reviews.llvm.org/D107152
This commit is contained in:
Dmitry Vyukov 2021-07-30 13:50:15 +02:00
parent 3ea3b6b2d4
commit 103d075b05
16 changed files with 82 additions and 83 deletions

View File

@ -409,8 +409,14 @@ inline void Trap() {
(void)enable_fp; \
} while (0)
constexpr u32 kInvalidTid = -1;
constexpr u32 kMainTid = 0;
// Internal thread identifier allocated by ThreadRegistry.
typedef u32 Tid;
constexpr Tid kInvalidTid = -1;
constexpr Tid kMainTid = 0;
// Stack depot stack identifier.
typedef u32 StackID;
const StackID kInvalidStackID = 0;
} // namespace __sanitizer

View File

@ -220,7 +220,7 @@ void __tsan_free(uptr p, uptr sz) {
void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
ThreadState *thr = AllocGoroutine();
*pthr = thr;
int goid = ThreadCreate(parent, (uptr)pc, 0, true);
Tid goid = ThreadCreate(parent, (uptr)pc, 0, true);
ThreadStart(thr, goid, 0, ThreadType::Regular);
}

View File

@ -26,8 +26,8 @@ struct FdSync {
struct FdDesc {
FdSync *sync;
int creation_tid;
u32 creation_stack;
Tid creation_tid;
StackID creation_stack;
};
struct FdContext {
@ -140,7 +140,7 @@ void FdOnFork(ThreadState *thr, uptr pc) {
}
}
bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) {
bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack) {
for (int l1 = 0; l1 < kTableSizeL1; l1++) {
FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
if (tab == 0)
@ -211,8 +211,8 @@ void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
MemoryResetRange(thr, pc, (uptr)d, 8);
unref(thr, pc, d->sync);
d->sync = 0;
d->creation_tid = 0;
d->creation_stack = 0;
d->creation_tid = kInvalidTid;
d->creation_stack = kInvalidStackID;
}
void FdFileCreate(ThreadState *thr, uptr pc, int fd) {

View File

@ -53,7 +53,7 @@ void FdSocketCreate(ThreadState *thr, uptr pc, int fd);
void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd);
void FdSocketConnecting(ThreadState *thr, uptr pc, int fd);
void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack);
bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack);
void FdOnFork(ThreadState *thr, uptr pc);
uptr File2addr(const char *path);

View File

@ -19,7 +19,7 @@ IgnoreSet::IgnoreSet()
: size_() {
}
void IgnoreSet::Add(u32 stack_id) {
void IgnoreSet::Add(StackID stack_id) {
if (size_ == kMaxSize)
return;
for (uptr i = 0; i < size_; i++) {
@ -37,7 +37,7 @@ uptr IgnoreSet::Size() const {
return size_;
}
u32 IgnoreSet::At(uptr i) const {
StackID IgnoreSet::At(uptr i) const {
CHECK_LT(i, size_);
CHECK_LE(size_, kMaxSize);
return stacks_[i];

View File

@ -22,14 +22,14 @@ class IgnoreSet {
static const uptr kMaxSize = 16;
IgnoreSet();
void Add(u32 stack_id);
void Add(StackID stack_id);
void Reset();
uptr Size() const;
u32 At(uptr i) const;
StackID At(uptr i) const;
private:
uptr size_;
u32 stacks_[kMaxSize];
StackID stacks_[kMaxSize];
};
} // namespace __tsan

View File

@ -1010,8 +1010,8 @@ TSAN_INTERCEPTOR(int, pthread_create,
ThreadIgnoreEnd(thr);
}
if (res == 0) {
int tid = ThreadCreate(thr, pc, *(uptr*)th, IsStateDetached(detached));
CHECK_NE(tid, 0);
Tid tid = ThreadCreate(thr, pc, *(uptr *)th, IsStateDetached(detached));
CHECK_NE(tid, kMainTid);
// Synchronization on p.tid serves two purposes:
// 1. ThreadCreate must finish before the new thread starts.
// Otherwise the new thread can call pthread_detach, but the pthread_t
@ -1030,7 +1030,7 @@ TSAN_INTERCEPTOR(int, pthread_create,
TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
int tid = ThreadConsumeTid(thr, pc, (uptr)th);
Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = BLOCK_REAL(pthread_join)(th, ret);
ThreadIgnoreEnd(thr);
@ -1044,7 +1044,7 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
SCOPED_INTERCEPTOR_RAW(pthread_detach, th);
int tid = ThreadConsumeTid(thr, pc, (uptr)th);
Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
int res = REAL(pthread_detach)(th);
if (res == 0) {
ThreadDetach(thr, pc, tid);
@ -1065,7 +1065,7 @@ TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
#if SANITIZER_LINUX
TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
SCOPED_INTERCEPTOR_RAW(pthread_tryjoin_np, th, ret);
int tid = ThreadConsumeTid(thr, pc, (uptr)th);
Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = REAL(pthread_tryjoin_np)(th, ret);
ThreadIgnoreEnd(thr);
@ -1079,7 +1079,7 @@ TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
const struct timespec *abstime) {
SCOPED_INTERCEPTOR_RAW(pthread_timedjoin_np, th, ret, abstime);
int tid = ThreadConsumeTid(thr, pc, (uptr)th);
Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
ThreadIgnoreEnd(thr);

View File

@ -215,8 +215,8 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
Processor *proc = ProcCreate();
ProcWire(proc, thr);
ThreadState *parent_thread_state = nullptr; // No parent.
int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
CHECK_NE(tid, 0);
Tid tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
CHECK_NE(tid, kMainTid);
ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
}
} else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {

View File

@ -52,7 +52,7 @@ ReportDesc::~ReportDesc() {
#if !SANITIZER_GO
const int kThreadBufSize = 32;
const char *thread_name(char *buf, int tid) {
const char *thread_name(char *buf, Tid tid) {
if (tid == kMainTid)
return "main thread";
internal_snprintf(buf, kThreadBufSize, "thread T%d", tid);
@ -378,7 +378,7 @@ void PrintReport(const ReportDesc *rep) {
#else // #if !SANITIZER_GO
const u32 kMainGoroutineId = 1;
const Tid kMainGoroutineId = 1;
void PrintStack(const ReportStack *ent) {
if (ent == 0 || ent->frames == 0) {

View File

@ -74,19 +74,19 @@ struct ReportLocation {
uptr heap_chunk_start = 0;
uptr heap_chunk_size = 0;
uptr external_tag = 0;
int tid = kInvalidTid;
Tid tid = kInvalidTid;
int fd = 0;
bool suppressable = false;
ReportStack *stack = nullptr;
};
struct ReportThread {
int id;
Tid id;
tid_t os_id;
bool running;
ThreadType thread_type;
char *name;
u32 parent_tid;
Tid parent_tid;
ReportStack *stack;
};
@ -106,7 +106,7 @@ class ReportDesc {
Vector<ReportLocation*> locs;
Vector<ReportMutex*> mutexes;
Vector<ReportThread*> threads;
Vector<int> unique_tids;
Vector<Tid> unique_tids;
ReportStack *sleep;
int count;

View File

@ -77,7 +77,7 @@ void OnInitialize() {
}
#endif
static ThreadContextBase *CreateThreadContext(u32 tid) {
static ThreadContextBase *CreateThreadContext(Tid tid) {
// Map thread trace when context is created.
char name[50];
internal_snprintf(name, sizeof(name), "trace %u", tid);
@ -126,7 +126,7 @@ Context::Context()
}
// The objects are allocated in TLS, so one may rely on zero-initialization.
ThreadState::ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
ThreadState::ThreadState(Context *ctx, Tid tid, int unique_id, u64 epoch,
unsigned reuse_count, uptr stk_addr, uptr stk_size,
uptr tls_addr, uptr tls_size)
: fast_state(tid, epoch)
@ -438,8 +438,8 @@ void Initialize(ThreadState *thr) {
(int)internal_getpid());
// Initialize thread 0.
int tid = ThreadCreate(thr, 0, 0, true);
CHECK_EQ(tid, 0);
Tid tid = ThreadCreate(thr, 0, 0, true);
CHECK_EQ(tid, kMainTid);
ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
#if TSAN_CONTAINS_UBSAN
__ubsan::InitAsPlugin();
@ -581,9 +581,9 @@ void GrowShadowStack(ThreadState *thr) {
}
#endif
u32 CurrentStackId(ThreadState *thr, uptr pc) {
StackID CurrentStackId(ThreadState *thr, uptr pc) {
if (!thr->is_inited) // May happen during bootstrap.
return 0;
return kInvalidStackID;
if (pc != 0) {
#if !SANITIZER_GO
DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
@ -594,7 +594,7 @@ u32 CurrentStackId(ThreadState *thr, uptr pc) {
thr->shadow_stack_pos[0] = pc;
thr->shadow_stack_pos++;
}
u32 id = StackDepotPut(
StackID id = StackDepotPut(
StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
if (pc != 0)
thr->shadow_stack_pos--;
@ -617,9 +617,7 @@ void TraceSwitch(ThreadState *thr) {
thr->nomalloc--;
}
Trace *ThreadTrace(int tid) {
return (Trace*)GetThreadTraceHeader(tid);
}
Trace *ThreadTrace(Tid tid) { return (Trace *)GetThreadTraceHeader(tid); }
uptr TraceTopPC(ThreadState *thr) {
Event *events = (Event*)GetThreadTrace(thr->tid);

View File

@ -400,7 +400,7 @@ struct ThreadState {
Vector<JmpBuf> jmp_bufs;
int ignore_interceptors;
#endif
const u32 tid;
const Tid tid;
const int unique_id;
bool in_symbolizer;
bool in_ignored_lib;
@ -428,7 +428,7 @@ struct ThreadState {
ThreadSignalContext *signal_ctx;
#if !SANITIZER_GO
u32 last_sleep_stack_id;
StackID last_sleep_stack_id;
ThreadClock last_sleep_clock;
#endif
@ -438,7 +438,7 @@ struct ThreadState {
const ReportDesc *current_report;
explicit ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
explicit ThreadState(Context *ctx, Tid tid, int unique_id, u64 epoch,
unsigned reuse_count, uptr stk_addr, uptr stk_size,
uptr tls_addr, uptr tls_size);
};
@ -469,10 +469,10 @@ inline void cur_thread_finalize() { }
class ThreadContext final : public ThreadContextBase {
public:
explicit ThreadContext(int tid);
explicit ThreadContext(Tid tid);
~ThreadContext();
ThreadState *thr;
u32 creation_stack_id;
StackID creation_stack_id;
SyncClock sync;
// Epoch at which the thread had started.
// If we see an event from the thread stamped by an older epoch,
@ -575,12 +575,12 @@ class ScopedReportBase {
const MutexSet *mset);
void AddStack(StackTrace stack, bool suppressable = false);
void AddThread(const ThreadContext *tctx, bool suppressable = false);
void AddThread(int unique_tid, bool suppressable = false);
void AddUniqueTid(int unique_tid);
void AddThread(Tid unique_tid, bool suppressable = false);
void AddUniqueTid(Tid unique_tid);
void AddMutex(const SyncVar *s);
u64 AddMutex(u64 id);
void AddLocation(uptr addr, uptr size);
void AddSleep(u32 stack_id);
void AddSleep(StackID stack_id);
void SetCount(int count);
const ReportDesc *GetReport() const;
@ -612,7 +612,7 @@ class ScopedReport : public ScopedReportBase {
bool ShouldReport(ThreadState *thr, ReportType typ);
ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
void RestoreStack(Tid tid, const u64 epoch, VarSizeStackTrace *stk,
MutexSet *mset, uptr *tag = nullptr);
// The stack could look like:
@ -678,8 +678,8 @@ bool IsExpectedReport(uptr addr, uptr size);
# define DPrintf2(...)
#endif
u32 CurrentStackId(ThreadState *thr, uptr pc);
ReportStack *SymbolizeStackId(u32 stack_id);
StackID CurrentStackId(ThreadState *thr, uptr pc);
ReportStack *SymbolizeStackId(StackID stack_id);
void PrintCurrentStack(ThreadState *thr, uptr pc);
void PrintCurrentStackSlow(uptr pc); // uses libunwind
MBlock *JavaHeapBlock(uptr addr, uptr *start);
@ -742,18 +742,18 @@ void ThreadIgnoreSyncEnd(ThreadState *thr);
void FuncEntry(ThreadState *thr, uptr pc);
void FuncExit(ThreadState *thr);
int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
ThreadType thread_type);
void ThreadFinish(ThreadState *thr);
int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
void ThreadJoin(ThreadState *thr, uptr pc, int tid);
void ThreadDetach(ThreadState *thr, uptr pc, int tid);
Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
void ThreadJoin(ThreadState *thr, uptr pc, Tid tid);
void ThreadDetach(ThreadState *thr, uptr pc, Tid tid);
void ThreadFinalize(ThreadState *thr);
void ThreadSetName(ThreadState *thr, const char *name);
int ThreadCount(ThreadState *thr);
void ProcessPendingSignals(ThreadState *thr);
void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid);
void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid);
Processor *ProcCreate();
void ProcDestroy(Processor *proc);
@ -818,7 +818,7 @@ void TraceSwitch(ThreadState *thr);
uptr TraceTopPC(ThreadState *thr);
uptr TraceSize();
uptr TraceParts();
Trace *ThreadTrace(int tid);
Trace *ThreadTrace(Tid tid);
extern "C" void __tsan_trace_switch();
void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,

View File

@ -35,7 +35,7 @@ struct Callback final : public DDCallback {
DDCallback::lt = thr->dd_lt;
}
u32 Unwind() override { return CurrentStackId(thr, pc); }
StackID Unwind() override { return CurrentStackId(thr, pc); }
int UniqueTid() override { return thr->unique_id; }
};

View File

@ -195,7 +195,7 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
}
}
void ScopedReportBase::AddUniqueTid(int unique_tid) {
void ScopedReportBase::AddUniqueTid(Tid unique_tid) {
rep_->unique_tids.PushBack(unique_tid);
}
@ -224,14 +224,14 @@ static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) {
return tctx->unique_id == (u32)unique_id;
}
static ThreadContext *FindThreadByUidLocked(int unique_id) {
static ThreadContext *FindThreadByUidLocked(Tid unique_id) {
ctx->thread_registry.CheckLocked();
return static_cast<ThreadContext *>(
ctx->thread_registry.FindThreadContextLocked(
FindThreadByUidLockedCallback, &unique_id));
}
static ThreadContext *FindThreadByTidLocked(int tid) {
static ThreadContext *FindThreadByTidLocked(Tid tid) {
ctx->thread_registry.CheckLocked();
return static_cast<ThreadContext *>(
ctx->thread_registry.GetThreadLocked(tid));
@ -262,7 +262,7 @@ ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
}
#endif
void ScopedReportBase::AddThread(int unique_tid, bool suppressable) {
void ScopedReportBase::AddThread(Tid unique_tid, bool suppressable) {
#if !SANITIZER_GO
if (const ThreadContext *tctx = FindThreadByUidLocked(unique_tid))
AddThread(tctx, suppressable);
@ -319,8 +319,8 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
return;
#if !SANITIZER_GO
int fd = -1;
int creat_tid = kInvalidTid;
u32 creat_stack = 0;
Tid creat_tid = kInvalidTid;
StackID creat_stack = 0;
if (FdLocation(addr, &fd, &creat_tid, &creat_stack)) {
auto *loc = New<ReportLocation>();
loc->type = ReportLocationFD;
@ -374,7 +374,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
}
#if !SANITIZER_GO
void ScopedReportBase::AddSleep(u32 stack_id) {
void ScopedReportBase::AddSleep(StackID stack_id) {
rep_->sleep = SymbolizeStackId(stack_id);
}
#endif
@ -388,7 +388,7 @@ ScopedReport::ScopedReport(ReportType typ, uptr tag)
ScopedReport::~ScopedReport() {}
void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
void RestoreStack(Tid tid, const u64 epoch, VarSizeStackTrace *stk,
MutexSet *mset, uptr *tag) {
// This function restores stack trace and mutex set for the thread/epoch.
// It does so by getting stack trace and mutex set at the beginning of

View File

@ -21,13 +21,8 @@ namespace __tsan {
// ThreadContext implementation.
ThreadContext::ThreadContext(int tid)
: ThreadContextBase(tid)
, thr()
, sync()
, epoch0()
, epoch1() {
}
ThreadContext::ThreadContext(Tid tid)
: ThreadContextBase(tid), thr(), sync(), epoch0(), epoch1() {}
#if !SANITIZER_GO
ThreadContext::~ThreadContext() {
@ -223,15 +218,15 @@ int ThreadCount(ThreadState *thr) {
return (int)result;
}
int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
OnCreatedArgs args = { thr, pc };
u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers.
int tid = ctx->thread_registry.CreateThread(uid, detached, parent_tid, &args);
Tid tid = ctx->thread_registry.CreateThread(uid, detached, parent_tid, &args);
DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid);
return tid;
}
void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
ThreadType thread_type) {
uptr stk_addr = 0;
uptr stk_size = 0;
@ -299,28 +294,28 @@ static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) {
return false;
}
int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
ConsumeThreadContext findCtx = {uid, nullptr};
ctx->thread_registry.FindThread(ConsumeThreadByUid, &findCtx);
int tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid;
Tid tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid;
DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, tid);
return tid;
}
void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
void ThreadJoin(ThreadState *thr, uptr pc, Tid tid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
ctx->thread_registry.JoinThread(tid, thr);
}
void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
void ThreadDetach(ThreadState *thr, uptr pc, Tid tid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
ctx->thread_registry.DetachThread(tid, thr);
}
void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
ctx->thread_registry.SetThreadUserId(tid, uid);
@ -421,7 +416,7 @@ ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) {
void *mem = Alloc(sizeof(ThreadState));
ThreadState *fiber = static_cast<ThreadState *>(mem);
internal_memset(fiber, 0, sizeof(*fiber));
int tid = ThreadCreate(thr, pc, 0, true);
Tid tid = ThreadCreate(thr, pc, 0, true);
FiberSwitchImpl(thr, fiber);
ThreadStart(fiber, tid, 0, ThreadType::Fiber);
FiberSwitchImpl(fiber, thr);

View File

@ -52,8 +52,8 @@ struct SyncVar {
uptr addr; // overwritten by DenseSlabAlloc freelist
Mutex mtx;
u64 uid; // Globally unique id.
u32 creation_stack_id;
u32 owner_tid; // Set only by exclusive owners.
StackID creation_stack_id;
Tid owner_tid; // Set only by exclusive owners.
u64 last_lock;
int recursion;
atomic_uint32_t flags;