sanitizer_thread_registry.h revision ce85e03620f64ce7e4cd0598f2e93090f52a9e99
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===-- sanitizer_thread_registry.h -----------------------------*- C++ -*-===// 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The LLVM Compiler Infrastructure 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// License. See LICENSE.TXT for details. 70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// 10558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// This file is shared between sanitizer tools. 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// General thread bookkeeping functionality. 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 15558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#ifndef SANITIZER_THREAD_REGISTRY_H 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define SANITIZER_THREAD_REGISTRY_H 17558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "sanitizer_common.h" 195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "sanitizer_list.h" 200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sanitizer_mutex.h" 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace __sanitizer { 23558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 24558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochenum ThreadStatus { 25558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ThreadStatusInvalid, // Non-existent thread, data is invalid. 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ThreadStatusCreated, // Created but not yet running. 27558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ThreadStatusRunning, // The thread is currently running. 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ThreadStatusFinished, // Joinable thread is finished but not yet joined. 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ThreadStatusDead // Joined, but some info is still available. 30558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}; 310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Generic thread context. Specific sanitizer tools may inherit from it. 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// If thread is dead, context may optionally be reused for a new thread. 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class ThreadContextBase { 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public: 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch explicit ThreadContextBase(u32 tid); 37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#ifndef SANITIZER_GO // Go does not have libstdc++ 38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch virtual 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~ThreadContextBase(); 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const u32 tid; // Thread ID. Main thread should have tid = 0. 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch u64 unique_id; // Unique thread ID. 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uptr os_id; // PID (used for reporting). 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uptr user_id; // Some opaque user thread id (e.g. pthread_t). 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch char name[64]; // As annotated by user. 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ThreadStatus status; 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool detached; 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int reuse_count; 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch u32 parent_tid; 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ThreadContextBase *next; // For storing thread contexts in a list. 54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void SetName(const char *new_name); 56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void SetDead(); 58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void SetJoined(void *arg); 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void SetFinished(); 60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void SetStarted(uptr _os_id, void *arg); 61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void SetCreated(uptr _user_id, u64 _unique_id, bool _detached, 62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch u32 _parent_tid, void *arg); 63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch void Reset(); 64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The following methods may be overriden by subclasses. 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Some of them take opaque arg that may be optionally be used 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // by subclasses. 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnDead() {} 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnJoined(void *arg) {} 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnFinished() {} 71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch virtual void OnStarted(void *arg) {} 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnCreated(void *arg) {} 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnReset() {} 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochtypedef ThreadContextBase* (*ThreadContextFactory)(u32 tid); 77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class ThreadRegistry { 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public: 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const u32 kUnknownTid; 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 82558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ThreadRegistry(ThreadContextFactory factory, u32 max_threads, 83558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch u32 thread_quarantine_size); 84558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch void GetNumberOfThreads(uptr *total = 0, uptr *running = 0, uptr *alive = 0); 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) uptr GetMaxAliveThreads(); 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Lock() { mtx_.Lock(); } 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void CheckLocked() { mtx_.CheckLocked(); } 89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Unlock() { mtx_.Unlock(); } 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Should be guarded by ThreadRegistryLock. 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ThreadContextBase *GetThreadLocked(u32 tid) { 93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK_LT(tid, n_contexts_); 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return threads_[tid]; 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg); 98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg); 100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Invokes callback with a specified arg for each thread context. 101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Should be guarded by ThreadRegistryLock. 102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg); 103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg); 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Finds a thread using the provided callback. Returns kUnknownTid if no 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // thread is found. 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch u32 FindThread(FindThreadCallback cb, void *arg); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Should be guarded by ThreadRegistryLock. Returns 0 if no thread 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // is found. 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb, 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void *arg); 1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SetThreadName(u32 tid, const char *name); 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void DetachThread(u32 tid); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void JoinThread(u32 tid, void *arg); 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void FinishThread(u32 tid); 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void StartThread(u32 tid, uptr os_id, void *arg); 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ThreadContextFactory context_factory_; 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const u32 max_threads_; 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const u32 thread_quarantine_size_; 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BlockingMutex mtx_; 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) u32 n_contexts_; // Number of created thread contexts, 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // at most max_threads_. 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) u64 total_threads_; // Total number of created threads. May be greater than 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // max_threads_ if contexts were reused. 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uptr alive_threads_; // Created or running. 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uptr max_alive_threads_; 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uptr running_threads_; 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ThreadContextBase **threads_; // Array of thread contexts is leaked. 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IntrusiveList<ThreadContextBase> dead_threads_; 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IntrusiveList<ThreadContextBase> invalid_threads_; 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void QuarantinePush(ThreadContextBase *tctx); 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ThreadContextBase *QuarantinePop(); 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdochtypedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock; 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace __sanitizer 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif // SANITIZER_THREAD_REGISTRY_H 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch