forked from OSchip/llvm-project
sanitizers: Introduce ThreadType enum
Replace bool workerthread flag with ThreadType enum. This change is preparation for fiber support. [dvyukov: fixed build of sanitizer_thread_registry_test.cc] Author: yuri (Yuri Per) Reviewed in: https://reviews.llvm.org/D57839 Context: https://reviews.llvm.org/D54889 llvm-svn: 353390
This commit is contained in:
parent
a822b1155e
commit
baf2f35ec4
|
@ -178,7 +178,7 @@ static void ThreadStartHook(void *hook, uptr os_id) {
|
|||
SetCurrentThread(thread);
|
||||
|
||||
// In lieu of AsanThread::ThreadStart.
|
||||
asanThreadRegistry().StartThread(thread->tid(), os_id, /*workerthread*/ false,
|
||||
asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -181,8 +181,8 @@ void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
|
|||
t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr,
|
||||
parent_tid, stack, /* detached */ true);
|
||||
t->Init();
|
||||
asanThreadRegistry().StartThread(t->tid(), GetTid(),
|
||||
/* workerthread */ true, 0);
|
||||
asanThreadRegistry().StartThread(t->tid(), GetTid(), ThreadType::Worker,
|
||||
nullptr);
|
||||
SetCurrentThread(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,8 +183,8 @@ static void ThreadStartHook(void *hook, uptr os_id) {
|
|||
// Determine whether we are starting or restarting the thread.
|
||||
if (status == ThreadStatusCreated)
|
||||
// In lieu of AsanThread::ThreadStart.
|
||||
asanThreadRegistry().StartThread(thread->tid(), os_id,
|
||||
/*workerthread*/ false, nullptr);
|
||||
asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
|
||||
nullptr);
|
||||
else {
|
||||
// In a thread restart, a thread may resume execution at an
|
||||
// arbitrary function entry point, with its stack and TLS state
|
||||
|
|
|
@ -245,8 +245,7 @@ void AsanThread::Init(const InitOptions *options) {
|
|||
thread_return_t AsanThread::ThreadStart(
|
||||
tid_t os_id, atomic_uintptr_t *signal_thread_is_registered) {
|
||||
Init();
|
||||
asanThreadRegistry().StartThread(tid(), os_id, /*workerthread*/ false,
|
||||
nullptr);
|
||||
asanThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular, nullptr);
|
||||
if (signal_thread_is_registered)
|
||||
atomic_store(signal_thread_is_registered, 1, memory_order_release);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) {
|
|||
/* arg */ nullptr);
|
||||
}
|
||||
|
||||
void ThreadStart(u32 tid, tid_t os_id, bool workerthread) {
|
||||
void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) {
|
||||
OnStartedArgs args;
|
||||
uptr stack_size = 0;
|
||||
uptr tls_size = 0;
|
||||
|
@ -86,7 +86,7 @@ void ThreadStart(u32 tid, tid_t os_id, bool workerthread) {
|
|||
args.tls_end = args.tls_begin + tls_size;
|
||||
GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
|
||||
args.dtls = DTLS_Get();
|
||||
thread_registry->StartThread(tid, os_id, workerthread, &args);
|
||||
thread_registry->StartThread(tid, os_id, thread_type, &args);
|
||||
}
|
||||
|
||||
void ThreadFinish() {
|
||||
|
|
|
@ -44,7 +44,8 @@ class ThreadContext : public ThreadContextBase {
|
|||
|
||||
void InitializeThreadRegistry();
|
||||
|
||||
void ThreadStart(u32 tid, tid_t os_id, bool workerthread = false);
|
||||
void ThreadStart(u32 tid, tid_t os_id,
|
||||
ThreadType thread_type = ThreadType::Regular);
|
||||
void ThreadFinish();
|
||||
u32 ThreadCreate(u32 tid, uptr uid, bool detached);
|
||||
void ThreadJoin(u32 tid);
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace __sanitizer {
|
|||
|
||||
ThreadContextBase::ThreadContextBase(u32 tid)
|
||||
: tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0),
|
||||
status(ThreadStatusInvalid),
|
||||
detached(false), workerthread(false), parent_tid(0), next(0) {
|
||||
status(ThreadStatusInvalid), detached(false),
|
||||
thread_type(ThreadType::Regular), parent_tid(0), next(0) {
|
||||
name[0] = '\0';
|
||||
atomic_store(&thread_destroyed, 0, memory_order_release);
|
||||
}
|
||||
|
@ -70,11 +70,11 @@ void ThreadContextBase::SetFinished() {
|
|||
OnFinished();
|
||||
}
|
||||
|
||||
void ThreadContextBase::SetStarted(tid_t _os_id, bool _workerthread,
|
||||
void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,
|
||||
void *arg) {
|
||||
status = ThreadStatusRunning;
|
||||
os_id = _os_id;
|
||||
workerthread = _workerthread;
|
||||
thread_type = _thread_type;
|
||||
OnStarted(arg);
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ void ThreadRegistry::FinishThread(u32 tid) {
|
|||
tctx->SetDestroyed();
|
||||
}
|
||||
|
||||
void ThreadRegistry::StartThread(u32 tid, tid_t os_id, bool workerthread,
|
||||
void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,
|
||||
void *arg) {
|
||||
BlockingMutexLock l(&mtx_);
|
||||
running_threads_++;
|
||||
|
@ -310,7 +310,7 @@ void ThreadRegistry::StartThread(u32 tid, tid_t os_id, bool workerthread,
|
|||
ThreadContextBase *tctx = threads_[tid];
|
||||
CHECK_NE(tctx, 0);
|
||||
CHECK_EQ(ThreadStatusCreated, tctx->status);
|
||||
tctx->SetStarted(os_id, workerthread, arg);
|
||||
tctx->SetStarted(os_id, thread_type, arg);
|
||||
}
|
||||
|
||||
void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) {
|
||||
|
|
|
@ -28,6 +28,11 @@ enum ThreadStatus {
|
|||
ThreadStatusDead // Joined, but some info is still available.
|
||||
};
|
||||
|
||||
enum class ThreadType {
|
||||
Regular, // Normal thread
|
||||
Worker, // macOS Grand Central Dispatch (GCD) worker thread
|
||||
};
|
||||
|
||||
// Generic thread context. Specific sanitizer tools may inherit from it.
|
||||
// If thread is dead, context may optionally be reused for a new thread.
|
||||
class ThreadContextBase {
|
||||
|
@ -44,7 +49,7 @@ class ThreadContextBase {
|
|||
|
||||
ThreadStatus status;
|
||||
bool detached;
|
||||
bool workerthread;
|
||||
ThreadType thread_type;
|
||||
|
||||
u32 parent_tid;
|
||||
ThreadContextBase *next; // For storing thread contexts in a list.
|
||||
|
@ -56,7 +61,7 @@ class ThreadContextBase {
|
|||
void SetDead();
|
||||
void SetJoined(void *arg);
|
||||
void SetFinished();
|
||||
void SetStarted(tid_t _os_id, bool _workerthread, void *arg);
|
||||
void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);
|
||||
void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
|
||||
u32 _parent_tid, void *arg);
|
||||
void Reset();
|
||||
|
@ -120,7 +125,7 @@ class ThreadRegistry {
|
|||
void DetachThread(u32 tid, void *arg);
|
||||
void JoinThread(u32 tid, void *arg);
|
||||
void FinishThread(u32 tid);
|
||||
void StartThread(u32 tid, tid_t os_id, bool workerthread, void *arg);
|
||||
void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg);
|
||||
void SetThreadUserId(u32 tid, uptr user_id);
|
||||
|
||||
private:
|
||||
|
|
|
@ -66,7 +66,7 @@ static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) {
|
|||
static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
|
||||
// Create and start a main thread.
|
||||
EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0));
|
||||
registry->StartThread(0, 0, false, 0);
|
||||
registry->StartThread(0, 0, ThreadType::Regular, 0);
|
||||
// Create a bunch of threads.
|
||||
for (u32 i = 1; i <= 10; i++) {
|
||||
EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0));
|
||||
|
@ -74,7 +74,7 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
|
|||
CheckThreadQuantity(registry, 11, 1, 11);
|
||||
// Start some of them.
|
||||
for (u32 i = 1; i <= 5; i++) {
|
||||
registry->StartThread(i, 0, false, 0);
|
||||
registry->StartThread(i, 0, ThreadType::Regular, 0);
|
||||
}
|
||||
CheckThreadQuantity(registry, 11, 6, 11);
|
||||
// Finish, create and start more threads.
|
||||
|
@ -84,7 +84,7 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
|
|||
registry->JoinThread(i, 0);
|
||||
}
|
||||
for (u32 i = 6; i <= 10; i++) {
|
||||
registry->StartThread(i, 0, false, 0);
|
||||
registry->StartThread(i, 0, ThreadType::Regular, 0);
|
||||
}
|
||||
std::vector<u32> new_tids;
|
||||
for (u32 i = 11; i <= 15; i++) {
|
||||
|
@ -111,7 +111,7 @@ static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) {
|
|||
}
|
||||
for (u32 i = 0; i < new_tids.size(); i++) {
|
||||
u32 tid = new_tids[i];
|
||||
registry->StartThread(tid, 0, false, 0);
|
||||
registry->StartThread(tid, 0, ThreadType::Regular, 0);
|
||||
registry->DetachThread(tid, 0);
|
||||
registry->FinishThread(tid);
|
||||
}
|
||||
|
@ -188,7 +188,8 @@ void *RunThread(void *arg) {
|
|||
tids.push_back(
|
||||
args->registry->CreateThread(0, false, 0, (void*)args->shard));
|
||||
for (int i = 0; i < kThreadsPerShard; i++)
|
||||
args->registry->StartThread(tids[i], 0, false, (void*)args->shard);
|
||||
args->registry->StartThread(tids[i], 0, ThreadType::Regular,
|
||||
(void*)args->shard);
|
||||
for (int i = 0; i < kThreadsPerShard; i++)
|
||||
args->registry->FinishThread(tids[i]);
|
||||
for (int i = 0; i < kThreadsPerShard; i++)
|
||||
|
@ -199,7 +200,7 @@ void *RunThread(void *arg) {
|
|||
static void ThreadedTestRegistry(ThreadRegistry *registry) {
|
||||
// Create and start a main thread.
|
||||
EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0));
|
||||
registry->StartThread(0, 0, false, 0);
|
||||
registry->StartThread(0, 0, ThreadType::Regular, 0);
|
||||
pthread_t threads[kNumShards];
|
||||
RunThreadArgs args[kNumShards];
|
||||
for (int i = 0; i < kNumShards; i++) {
|
||||
|
|
|
@ -213,7 +213,7 @@ void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
|
|||
ThreadState *thr = AllocGoroutine();
|
||||
*pthr = thr;
|
||||
int goid = ThreadCreate(parent, (uptr)pc, 0, true);
|
||||
ThreadStart(thr, goid, 0, /*workerthread*/ false);
|
||||
ThreadStart(thr, goid, 0, ThreadType::Regular);
|
||||
}
|
||||
|
||||
void __tsan_go_end(ThreadState *thr) {
|
||||
|
|
|
@ -958,7 +958,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
|
|||
internal_sched_yield();
|
||||
Processor *proc = ProcCreate();
|
||||
ProcWire(proc, thr);
|
||||
ThreadStart(thr, tid, GetTid(), /*workerthread*/ false);
|
||||
ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
|
||||
atomic_store(&p->tid, 0, memory_order_release);
|
||||
}
|
||||
void *res = callback(param);
|
||||
|
|
|
@ -212,7 +212,7 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
|
|||
ThreadState *parent_thread_state = nullptr; // No parent.
|
||||
int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
|
||||
CHECK_NE(tid, 0);
|
||||
ThreadStart(thr, tid, GetTid(), /*workerthread*/ true);
|
||||
ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
|
||||
}
|
||||
} else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
|
||||
if (thread == pthread_self()) {
|
||||
|
|
|
@ -257,7 +257,7 @@ static void PrintThread(const ReportThread *rt) {
|
|||
Printf(" '%s'", rt->name);
|
||||
char thrbuf[kThreadBufSize];
|
||||
const char *thread_status = rt->running ? "running" : "finished";
|
||||
if (rt->workerthread) {
|
||||
if (rt->thread_type == ThreadType::Worker) {
|
||||
Printf(" (tid=%zu, %s) is a GCD worker thread\n", rt->os_id, thread_status);
|
||||
Printf("\n");
|
||||
Printf("%s", d.Default());
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define TSAN_REPORT_H
|
||||
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
#include "sanitizer_common/sanitizer_thread_registry.h"
|
||||
#include "sanitizer_common/sanitizer_vector.h"
|
||||
#include "tsan_defs.h"
|
||||
|
||||
|
@ -91,7 +92,7 @@ struct ReportThread {
|
|||
int id;
|
||||
tid_t os_id;
|
||||
bool running;
|
||||
bool workerthread;
|
||||
ThreadType thread_type;
|
||||
char *name;
|
||||
u32 parent_tid;
|
||||
ReportStack *stack;
|
||||
|
|
|
@ -396,7 +396,7 @@ void Initialize(ThreadState *thr) {
|
|||
// Initialize thread 0.
|
||||
int tid = ThreadCreate(thr, 0, 0, true);
|
||||
CHECK_EQ(tid, 0);
|
||||
ThreadStart(thr, tid, GetTid(), /*workerthread*/ false);
|
||||
ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
|
||||
#if TSAN_CONTAINS_UBSAN
|
||||
__ubsan::InitAsPlugin();
|
||||
#endif
|
||||
|
|
|
@ -764,7 +764,8 @@ 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, bool workerthread);
|
||||
void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
|
||||
ThreadType thread_type);
|
||||
void ThreadFinish(ThreadState *thr);
|
||||
int ThreadTid(ThreadState *thr, uptr pc, uptr uid);
|
||||
void ThreadJoin(ThreadState *thr, uptr pc, int tid);
|
||||
|
|
|
@ -201,7 +201,7 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
|
|||
rt->running = (tctx->status == ThreadStatusRunning);
|
||||
rt->name = internal_strdup(tctx->name);
|
||||
rt->parent_tid = tctx->parent_tid;
|
||||
rt->workerthread = tctx->workerthread;
|
||||
rt->thread_type = tctx->thread_type;
|
||||
rt->stack = 0;
|
||||
rt->stack = SymbolizeStackId(tctx->creation_stack_id);
|
||||
if (rt->stack)
|
||||
|
|
|
@ -239,7 +239,8 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
|
|||
return tid;
|
||||
}
|
||||
|
||||
void ThreadStart(ThreadState *thr, int tid, tid_t os_id, bool workerthread) {
|
||||
void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
|
||||
ThreadType thread_type) {
|
||||
uptr stk_addr = 0;
|
||||
uptr stk_size = 0;
|
||||
uptr tls_addr = 0;
|
||||
|
@ -257,7 +258,7 @@ void ThreadStart(ThreadState *thr, int tid, tid_t os_id, bool workerthread) {
|
|||
|
||||
ThreadRegistry *tr = ctx->thread_registry;
|
||||
OnStartedArgs args = { thr, stk_addr, stk_size, tls_addr, tls_size };
|
||||
tr->StartThread(tid, os_id, workerthread, &args);
|
||||
tr->StartThread(tid, os_id, thread_type, &args);
|
||||
|
||||
tr->Lock();
|
||||
thr->tctx = (ThreadContext*)tr->GetThreadLocked(tid);
|
||||
|
|
Loading…
Reference in New Issue