forked from OSchip/llvm-project
tsan: store ThreadRegistry in Context by value
It's unclear why we allocate ThreadRegistry separately, I assume it's some historical leftover. Embed ThreadRegistry into Context. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D107045
This commit is contained in:
parent
4e15ee2867
commit
0d68cfc996
|
@ -215,9 +215,9 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
|
|||
} else {
|
||||
// TODO(kuba.brecka): We should not lock. This is supposed to be called
|
||||
// from within the debugger when other threads are stopped.
|
||||
ctx->thread_registry->Lock();
|
||||
ctx->thread_registry.Lock();
|
||||
ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack);
|
||||
ctx->thread_registry->Unlock();
|
||||
ctx->thread_registry.Unlock();
|
||||
if (tctx) {
|
||||
region_kind = is_stack ? "stack" : "tls";
|
||||
} else {
|
||||
|
@ -252,7 +252,7 @@ int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
|
|||
*thread_id = b->tid;
|
||||
// No locking. This is supposed to be called from within the debugger when
|
||||
// other threads are stopped.
|
||||
ThreadContextBase *tctx = ctx->thread_registry->GetThreadLocked(b->tid);
|
||||
ThreadContextBase *tctx = ctx->thread_registry.GetThreadLocked(b->tid);
|
||||
*os_id = tctx->os_id;
|
||||
|
||||
StackTrace stack = StackDepotGet(b->stk);
|
||||
|
|
|
@ -1986,7 +1986,7 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
|
|||
// StackTrace::GetNestInstructionPc(pc) is used because return address is
|
||||
// expected, OutputReport() will undo this.
|
||||
ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ScopedReport rep(ReportTypeErrnoInSignal);
|
||||
if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
|
||||
rep.AddStack(stack, true);
|
||||
|
@ -2348,7 +2348,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
|
|||
ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
|
||||
|
||||
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
|
||||
__tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
|
||||
__tsan::ctx->thread_registry.SetThreadNameByUserId(thread, name)
|
||||
|
||||
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
|
|||
ObtainCurrentStack(thr, pc, &stack);
|
||||
if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
|
||||
return;
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ScopedReport rep(ReportTypeSignalUnsafe);
|
||||
rep.AddStack(stack, true);
|
||||
OutputReport(thr, rep);
|
||||
|
|
|
@ -77,8 +77,6 @@ void OnInitialize() {
|
|||
}
|
||||
#endif
|
||||
|
||||
static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)];
|
||||
|
||||
static ThreadContextBase *CreateThreadContext(u32 tid) {
|
||||
// Map thread trace when context is created.
|
||||
char name[50];
|
||||
|
@ -118,8 +116,8 @@ Context::Context()
|
|||
report_mtx(MutexTypeReport),
|
||||
nreported(),
|
||||
nmissed_expected(),
|
||||
thread_registry(new (thread_registry_placeholder) ThreadRegistry(
|
||||
CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse)),
|
||||
thread_registry(CreateThreadContext, kMaxTid, kThreadQuarantineSize,
|
||||
kMaxTidReuse),
|
||||
racy_mtx(MutexTypeRacy),
|
||||
racy_stacks(),
|
||||
racy_addresses(),
|
||||
|
@ -161,7 +159,7 @@ ThreadState::ThreadState(Context *ctx, u32 tid, int unique_id, u64 epoch,
|
|||
static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
|
||||
uptr n_threads;
|
||||
uptr n_running_threads;
|
||||
ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
|
||||
ctx->thread_registry.GetNumberOfThreads(&n_threads, &n_running_threads);
|
||||
InternalMmapVector<char> buf(4096);
|
||||
WriteMemoryProfile(buf.data(), buf.size(), n_threads, n_running_threads);
|
||||
WriteToFile(fd, buf.data(), internal_strlen(buf.data()));
|
||||
|
@ -526,7 +524,7 @@ int Finalize(ThreadState *thr) {
|
|||
|
||||
#if !SANITIZER_GO
|
||||
void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
|
||||
ctx->thread_registry->Lock();
|
||||
ctx->thread_registry.Lock();
|
||||
ctx->report_mtx.Lock();
|
||||
ScopedErrorReportLock::Lock();
|
||||
// Suppress all reports in the pthread_atfork callbacks.
|
||||
|
@ -545,7 +543,7 @@ void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
|
|||
thr->ignore_interceptors--;
|
||||
ScopedErrorReportLock::Unlock();
|
||||
ctx->report_mtx.Unlock();
|
||||
ctx->thread_registry->Unlock();
|
||||
ctx->thread_registry.Unlock();
|
||||
}
|
||||
|
||||
void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
|
||||
|
@ -553,10 +551,10 @@ void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS {
|
|||
thr->ignore_interceptors--;
|
||||
ScopedErrorReportLock::Unlock();
|
||||
ctx->report_mtx.Unlock();
|
||||
ctx->thread_registry->Unlock();
|
||||
ctx->thread_registry.Unlock();
|
||||
|
||||
uptr nthread = 0;
|
||||
ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);
|
||||
ctx->thread_registry.GetNumberOfThreads(0, 0, &nthread /* alive threads */);
|
||||
VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
|
||||
" parent had %d threads\n", (int)internal_getpid(), (int)nthread);
|
||||
if (nthread == 1) {
|
||||
|
|
|
@ -530,7 +530,7 @@ struct Context {
|
|||
void *background_thread;
|
||||
atomic_uint32_t stop_background_thread;
|
||||
|
||||
ThreadRegistry *thread_registry;
|
||||
ThreadRegistry thread_registry;
|
||||
|
||||
Mutex racy_mtx;
|
||||
Vector<RacyStacks> racy_stacks;
|
||||
|
|
|
@ -53,7 +53,7 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
|
|||
return;
|
||||
if (!ShouldReport(thr, typ))
|
||||
return;
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ScopedReport rep(typ);
|
||||
rep.AddMutex(mid);
|
||||
VarSizeStackTrace trace;
|
||||
|
@ -107,7 +107,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) NO_THREAD_SAF
|
|||
s->Reset(thr->proc()); // must not reset it before the report is printed
|
||||
s->mtx.Unlock();
|
||||
if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked)) {
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ScopedReport rep(ReportTypeMutexDestroyLocked);
|
||||
rep.AddMutex(mid);
|
||||
VarSizeStackTrace trace;
|
||||
|
@ -417,9 +417,8 @@ void AcquireGlobal(ThreadState *thr) {
|
|||
DPrintf("#%d: AcquireGlobal\n", thr->tid);
|
||||
if (thr->ignore_sync)
|
||||
return;
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ctx->thread_registry->RunCallbackForEachThreadLocked(
|
||||
UpdateClockCallback, thr);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ctx->thread_registry.RunCallbackForEachThreadLocked(UpdateClockCallback, thr);
|
||||
}
|
||||
|
||||
void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) NO_THREAD_SAFETY_ANALYSIS {
|
||||
|
@ -473,9 +472,9 @@ void AfterSleep(ThreadState *thr, uptr pc) {
|
|||
if (thr->ignore_sync)
|
||||
return;
|
||||
thr->last_sleep_stack_id = CurrentStackId(thr, pc);
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ctx->thread_registry->RunCallbackForEachThreadLocked(
|
||||
UpdateSleepClockCallback, thr);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ctx->thread_registry.RunCallbackForEachThreadLocked(UpdateSleepClockCallback,
|
||||
thr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -521,7 +520,7 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
|
|||
void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
|
||||
if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
|
||||
return;
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
ScopedReport rep(ReportTypeDeadlock);
|
||||
for (int i = 0; i < r->n; i++) {
|
||||
rep.AddMutex(r->loop[i].mtx_ctx0);
|
||||
|
|
|
@ -134,7 +134,7 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
|
|||
CheckedMutex::CheckNoLocks();
|
||||
// For the same reason check we didn't lock thread_registry yet.
|
||||
if (SANITIZER_DEBUG)
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
if (!flags()->report_bugs || thr->suppress_reports)
|
||||
return false;
|
||||
switch (typ) {
|
||||
|
@ -156,7 +156,7 @@ bool ShouldReport(ThreadState *thr, ReportType typ) {
|
|||
}
|
||||
|
||||
ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
|
||||
ctx->thread_registry->CheckLocked();
|
||||
ctx->thread_registry.CheckLocked();
|
||||
void *mem = internal_alloc(sizeof(ReportDesc));
|
||||
rep_ = new(mem) ReportDesc;
|
||||
rep_->typ = typ;
|
||||
|
@ -229,16 +229,16 @@ static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) {
|
|||
}
|
||||
|
||||
static ThreadContext *FindThreadByUidLocked(int unique_id) {
|
||||
ctx->thread_registry->CheckLocked();
|
||||
ctx->thread_registry.CheckLocked();
|
||||
return static_cast<ThreadContext *>(
|
||||
ctx->thread_registry->FindThreadContextLocked(
|
||||
ctx->thread_registry.FindThreadContextLocked(
|
||||
FindThreadByUidLockedCallback, &unique_id));
|
||||
}
|
||||
|
||||
static ThreadContext *FindThreadByTidLocked(int tid) {
|
||||
ctx->thread_registry->CheckLocked();
|
||||
return static_cast<ThreadContext*>(
|
||||
ctx->thread_registry->GetThreadLocked(tid));
|
||||
ctx->thread_registry.CheckLocked();
|
||||
return static_cast<ThreadContext *>(
|
||||
ctx->thread_registry.GetThreadLocked(tid));
|
||||
}
|
||||
|
||||
static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
|
||||
|
@ -253,10 +253,10 @@ static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
|
|||
}
|
||||
|
||||
ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
|
||||
ctx->thread_registry->CheckLocked();
|
||||
ThreadContext *tctx = static_cast<ThreadContext*>(
|
||||
ctx->thread_registry->FindThreadContextLocked(IsInStackOrTls,
|
||||
(void*)addr));
|
||||
ctx->thread_registry.CheckLocked();
|
||||
ThreadContext *tctx =
|
||||
static_cast<ThreadContext *>(ctx->thread_registry.FindThreadContextLocked(
|
||||
IsInStackOrTls, (void *)addr));
|
||||
if (!tctx)
|
||||
return 0;
|
||||
ThreadState *thr = tctx->thr;
|
||||
|
@ -697,7 +697,7 @@ void ReportRace(ThreadState *thr) {
|
|||
}
|
||||
}
|
||||
|
||||
ThreadRegistryLock l0(ctx->thread_registry);
|
||||
ThreadRegistryLock l0(&ctx->thread_registry);
|
||||
ScopedReport rep(typ, tag);
|
||||
for (uptr i = 0; i < kMop; i++) {
|
||||
Shadow s(thr->racy_state[i]);
|
||||
|
@ -707,8 +707,8 @@ void ReportRace(ThreadState *thr) {
|
|||
|
||||
for (uptr i = 0; i < kMop; i++) {
|
||||
FastState s(thr->racy_state[i]);
|
||||
ThreadContext *tctx = static_cast<ThreadContext*>(
|
||||
ctx->thread_registry->GetThreadLocked(s.tid()));
|
||||
ThreadContext *tctx = static_cast<ThreadContext *>(
|
||||
ctx->thread_registry.GetThreadLocked(s.tid()));
|
||||
if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1)
|
||||
continue;
|
||||
rep.AddThread(tctx);
|
||||
|
|
|
@ -205,10 +205,10 @@ void ThreadFinalize(ThreadState *thr) {
|
|||
#if !SANITIZER_GO
|
||||
if (!ShouldReport(thr, ReportTypeThreadLeak))
|
||||
return;
|
||||
ThreadRegistryLock l(ctx->thread_registry);
|
||||
ThreadRegistryLock l(&ctx->thread_registry);
|
||||
Vector<ThreadLeak> leaks;
|
||||
ctx->thread_registry->RunCallbackForEachThreadLocked(
|
||||
MaybeReportThreadLeak, &leaks);
|
||||
ctx->thread_registry.RunCallbackForEachThreadLocked(MaybeReportThreadLeak,
|
||||
&leaks);
|
||||
for (uptr i = 0; i < leaks.Size(); i++) {
|
||||
ScopedReport rep(ReportTypeThreadLeak);
|
||||
rep.AddThread(leaks[i].tctx, true);
|
||||
|
@ -220,15 +220,14 @@ void ThreadFinalize(ThreadState *thr) {
|
|||
|
||||
int ThreadCount(ThreadState *thr) {
|
||||
uptr result;
|
||||
ctx->thread_registry->GetNumberOfThreads(0, 0, &result);
|
||||
ctx->thread_registry.GetNumberOfThreads(0, 0, &result);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
int 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);
|
||||
int tid = ctx->thread_registry.CreateThread(uid, detached, parent_tid, &args);
|
||||
DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid);
|
||||
return tid;
|
||||
}
|
||||
|
@ -252,7 +251,7 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
|
|||
}
|
||||
#endif
|
||||
|
||||
ThreadRegistry *tr = ctx->thread_registry;
|
||||
ThreadRegistry *tr = &ctx->thread_registry;
|
||||
OnStartedArgs args = { thr, stk_addr, stk_size, tls_addr, tls_size };
|
||||
tr->StartThread(tid, os_id, thread_type, &args);
|
||||
|
||||
|
@ -276,7 +275,7 @@ void ThreadFinish(ThreadState *thr) {
|
|||
if (thr->tls_addr && thr->tls_size)
|
||||
DontNeedShadowFor(thr->tls_addr, thr->tls_size);
|
||||
thr->is_dead = true;
|
||||
ctx->thread_registry->FinishThread(thr->tid);
|
||||
ctx->thread_registry.FinishThread(thr->tid);
|
||||
}
|
||||
|
||||
struct ConsumeThreadContext {
|
||||
|
@ -303,7 +302,7 @@ static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) {
|
|||
|
||||
int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
|
||||
ConsumeThreadContext findCtx = {uid, nullptr};
|
||||
ctx->thread_registry->FindThread(ConsumeThreadByUid, &findCtx);
|
||||
ctx->thread_registry.FindThread(ConsumeThreadByUid, &findCtx);
|
||||
int tid = findCtx.tctx ? findCtx.tctx->tid : kInvalidTid;
|
||||
DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, tid);
|
||||
return tid;
|
||||
|
@ -313,23 +312,23 @@ void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
|
|||
CHECK_GT(tid, 0);
|
||||
CHECK_LT(tid, kMaxTid);
|
||||
DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
|
||||
ctx->thread_registry->JoinThread(tid, thr);
|
||||
ctx->thread_registry.JoinThread(tid, thr);
|
||||
}
|
||||
|
||||
void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
|
||||
CHECK_GT(tid, 0);
|
||||
CHECK_LT(tid, kMaxTid);
|
||||
ctx->thread_registry->DetachThread(tid, thr);
|
||||
ctx->thread_registry.DetachThread(tid, thr);
|
||||
}
|
||||
|
||||
void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
|
||||
CHECK_GT(tid, 0);
|
||||
CHECK_LT(tid, kMaxTid);
|
||||
ctx->thread_registry->SetThreadUserId(tid, uid);
|
||||
ctx->thread_registry.SetThreadUserId(tid, uid);
|
||||
}
|
||||
|
||||
void ThreadSetName(ThreadState *thr, const char *name) {
|
||||
ctx->thread_registry->SetThreadName(thr->tid, name);
|
||||
ctx->thread_registry.SetThreadName(thr->tid, name);
|
||||
}
|
||||
|
||||
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
|
||||
|
|
Loading…
Reference in New Issue