sanitizer_thread_registry.h revision 827d4ef8b76760ef8c58612d916b8f53081bf368
16d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===-- sanitizer_thread_registry.h -----------------------------*- C++ -*-===// 26d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 36d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// The LLVM Compiler Infrastructure 46d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 56d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// This file is distributed under the University of Illinois Open Source 66d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// License. See LICENSE.TXT for details. 76d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 86d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===----------------------------------------------------------------------===// 96d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// This file is shared between sanitizer tools. 116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// General thread bookkeeping functionality. 136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===----------------------------------------------------------------------===// 146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#ifndef SANITIZER_THREAD_REGISTRY_H 166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#define SANITIZER_THREAD_REGISTRY_H 176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include "sanitizer_common.h" 196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include "sanitizer_list.h" 206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include "sanitizer_mutex.h" 216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnamespace __sanitizer { 236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovenum ThreadStatus { 256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadStatusInvalid, // Non-existent thread, data is invalid. 266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadStatusCreated, // Created but not yet running. 276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadStatusRunning, // The thread is currently running. 286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadStatusFinished, // Joinable thread is finished but not yet joined. 296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadStatusDead // Joined, but some info is still available. 306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}; 316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// Generic thread context. Specific sanitizer tools may inherit from it. 336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// If thread is dead, context may optionally be reused for a new thread. 346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovclass ThreadContextBase { 356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov public: 366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov explicit ThreadContextBase(u32 tid); 376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov const u32 tid; // Thread ID. Main thread should have tid = 0. 396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u64 unique_id; // Unique thread ID. 406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr os_id; // PID (used for reporting). 416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr user_id; // Some opaque user thread id (e.g. pthread_t). 426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov char name[64]; // As annotated by user. 436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadStatus status; 456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov bool detached; 466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov int reuse_count; 476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 parent_tid; 496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *next; // For storing thread contexts in a list. 506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetName(const char *new_name); 526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetDead(); 546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetJoined(void *arg); 556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetFinished(); 566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetStarted(uptr _os_id, void *arg); 576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetCreated(uptr _user_id, u64 _unique_id, bool _detached, 586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 _parent_tid, void *arg); 596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void Reset(void *arg); 606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // The following methods may be overriden by subclasses. 626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Some of them take opaque arg that may be optionally be used 636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // by subclasses. 646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov virtual void OnDead() {} 656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov virtual void OnJoined(void *arg) {} 666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov virtual void OnFinished() {} 676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov virtual void OnStarted(void *arg) {} 686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov virtual void OnCreated(void *arg) {} 696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov virtual void OnReset(void *arg) {} 706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}; 716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovtypedef ThreadContextBase* (*ThreadContextFactory)(u32 tid); 736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovclass ThreadRegistry { 756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov private: 766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov const ThreadContextFactory context_factory_; 776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov const u32 max_threads_; 786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov const u32 thread_quarantine_size_; 796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutex mtx_; 816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 n_contexts_; // Number of created thread contexts, 836d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // at most max_threads_. 846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u64 total_threads_; // Total number of created threads. May be greater than 856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // max_threads_ if contexts were reused. 866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr alive_threads_; // Created or running. 876d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr max_alive_threads_; 886d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr running_threads_; 896d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 906d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase **threads_; // Array of thread contexts is leaked. 916d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov IntrusiveList<ThreadContextBase> dead_threads_; 926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov public: 94827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov static const u32 kUnknownTid; 95827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov 966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistry(ThreadContextFactory factory, u32 max_threads, 976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 thread_quarantine_size); 986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void GetNumberOfThreads(uptr *total = 0, uptr *running = 0, uptr *alive = 0); 996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr GetMaxAliveThreads(); 1006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void Lock() { mtx_.Lock(); } 1026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void CheckLocked() { mtx_.CheckLocked(); } 1036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void Unlock() { mtx_.Unlock(); } 1046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Should be guarded by ThreadRegistryLock. 1066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *GetThreadLocked(u32 tid) { 1076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov DCHECK_LT(tid, n_contexts_); 1086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return threads_[tid]; 1096d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg); 1126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg); 1146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Invokes callback with a specified arg for each thread context. 1156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Should be guarded by ThreadRegistryLock. 1166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg); 1176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg); 1196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Finds a thread using the provided callback. Returns kUnknownTid if no 1206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // thread is found. 1216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 FindThread(FindThreadCallback cb, void *arg); 1226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Should be guarded by ThreadRegistryLock. Returns 0 if no thread 1236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // is found. 1246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb, 1256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void *arg); 1266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void SetThreadName(u32 tid, const char *name); 1286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void DetachThread(u32 tid); 1296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void JoinThread(u32 tid, void *arg); 1306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void FinishThread(u32 tid); 1316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void StartThread(u32 tid, uptr os_id, void *arg); 1326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}; 1336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovtypedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock; 1356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} // namespace __sanitizer 1376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#endif // SANITIZER_THREAD_REGISTRY_H 1396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 140