sanitizer_thread_registry.cc revision e174cd1ee373c3b77f3ce8e7fc62f70d0668d03d
16d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===-- sanitizer_thread_registry.cc --------------------------------------===// 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#include "sanitizer_thread_registry.h" 166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnamespace __sanitizer { 186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovThreadContextBase::ThreadContextBase(u32 tid) 206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov : tid(tid), unique_id(0), os_id(0), user_id(0), status(ThreadStatusInvalid), 216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov detached(false), reuse_count(0), parent_tid(0), next(0) { 226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name[0] = '\0'; 236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 256af642eaf764434ac6f28f242e7f081156bce9e3Dmitry VyukovThreadContextBase::~ThreadContextBase() { 26e374e4ece521692173aad355420d03e1b2cd819aAlexey Samsonov // ThreadContextBase should never be deleted. 276af642eaf764434ac6f28f242e7f081156bce9e3Dmitry Vyukov CHECK(0); 286af642eaf764434ac6f28f242e7f081156bce9e3Dmitry Vyukov} 29c7bc60cd4bfe21868aacd8a87b13590b314ed330Eric Christopher 306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetName(const char *new_name) { 316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name[0] = '\0'; 326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (new_name) { 336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov internal_strncpy(name, new_name, sizeof(name)); 346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name[sizeof(name) - 1] = '\0'; 356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetDead() { 396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK(status == ThreadStatusRunning || 406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status == ThreadStatusFinished); 416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusDead; 426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov user_id = 0; 436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnDead(); 446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetJoined(void *arg) { 476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // FIXME(dvyukov): print message and continue (it's user error). 486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(false, detached); 496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusFinished, status); 506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusDead; 516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov user_id = 0; 526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnJoined(arg); 536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetFinished() { 566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (!detached) 576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusFinished; 586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnFinished(); 596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetStarted(uptr _os_id, void *arg) { 626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusRunning; 636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov os_id = _os_id; 646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnStarted(arg); 656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id, 686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov bool _detached, u32 _parent_tid, void *arg) { 696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusCreated; 706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov user_id = _user_id; 716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov unique_id = _unique_id; 726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov detached = _detached; 736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Parent tid makes no sense for the main thread. 746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tid != 0) 756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov parent_tid = _parent_tid; 766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnCreated(arg); 776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 79ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukovvoid ThreadContextBase::Reset() { 806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusInvalid; 816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov reuse_count++; 826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov SetName(0); 83ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov OnReset(); 846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// ThreadRegistry implementation. 876d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 88e174cd1ee373c3b77f3ce8e7fc62f70d0668d03dTimur Iskhodzhanovconst u32 ThreadRegistry::kUnknownTid = ~0U; 89827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov 906d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads, 916d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 thread_quarantine_size) 926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov : context_factory_(factory), 936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov max_threads_(max_threads), 946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov thread_quarantine_size_(thread_quarantine_size), 956d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov mtx_(), 966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov n_contexts_(0), 976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov total_threads_(0), 986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov alive_threads_(0), 996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov max_alive_threads_(0), 1006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov running_threads_(0) { 1016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov threads_ = (ThreadContextBase **)MmapOrDie(max_threads_ * sizeof(threads_[0]), 1026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov "ThreadRegistry"); 1036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov dead_threads_.clear(); 104ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov invalid_threads_.clear(); 1056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running, 1086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr *alive) { 1096d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (total) *total = n_contexts_; 1116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (running) *running = running_threads_; 1126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (alive) *alive = alive_threads_; 1136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovuptr ThreadRegistry::GetMaxAliveThreads() { 1166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return max_alive_threads_; 1186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovu32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, 1216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void *arg) { 1226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 tid = kUnknownTid; 124ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov ThreadContextBase *tctx = QuarantinePop(); 125ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov if (tctx) { 1266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tid = tctx->tid; 127ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov } else if (n_contexts_ < max_threads_) { 1286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Allocate new thread context and tid. 1296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tid = n_contexts_++; 1306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx = context_factory_(tid); 1316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov threads_[tid] = tctx; 132ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov } else { 133ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov Report("%s: Thread limit (%u threads) exceeded. Dying.\n", 134ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov SanitizerToolName, max_threads_); 135ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov Die(); 1366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 1386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tid, kUnknownTid); 1396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, max_threads_); 1406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(tctx->status, ThreadStatusInvalid); 1416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov alive_threads_++; 1426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (max_alive_threads_ < alive_threads_) { 1436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov max_alive_threads_++; 1446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(alive_threads_, max_alive_threads_); 1456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetCreated(user_id, total_threads_++, detached, 1476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov parent_tid, arg); 1486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tid; 1496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb, 1526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void *arg) { 1536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckLocked(); 1546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (u32 tid = 0; tid < n_contexts_; tid++) { 1556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx == 0) 1576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov continue; 1586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov cb(tctx, arg); 1596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovu32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) { 1636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (u32 tid = 0; tid < n_contexts_; tid++) { 1656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx != 0 && cb(tctx, arg)) 1676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tctx->tid; 1686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return kUnknownTid; 1706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovThreadContextBase * 1736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) { 1746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckLocked(); 1756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (u32 tid = 0; tid < n_contexts_; tid++) { 1766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx != 0 && cb(tctx, arg)) 1786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tctx; 1796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return 0; 1816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 18398d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveevstatic bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx, 18498d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev void *arg) { 18598d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid && 18698d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev tctx->status != ThreadStatusDead); 18798d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev} 18898d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev 18998d3b40ec5cf06e46397492c21acc9d18e8c54abSergey MatveevThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(uptr os_id) { 19098d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev return FindThreadContextLocked(FindThreadContextByOsIdCallback, 19198d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev (void *)os_id); 19298d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev} 19398d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev 1946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::SetThreadName(u32 tid, const char *name) { 1956d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 1976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 1996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusRunning, tctx->status); 2006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetName(name); 2016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::DetachThread(u32 tid) { 2046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->status == ThreadStatusInvalid) { 2096d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov Report("%s: Detach of non-existent thread\n", SanitizerToolName); 2106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return; 2116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->status == ThreadStatusFinished) { 2136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetDead(); 214ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov QuarantinePush(tctx); 2156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } else { 2166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->detached = true; 2176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::JoinThread(u32 tid, void *arg) { 2216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->status == ThreadStatusInvalid) { 2266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov Report("%s: Join of non-existent thread\n", SanitizerToolName); 2276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return; 2286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetJoined(arg); 230ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov QuarantinePush(tctx); 2316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::FinishThread(u32 tid) { 2346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_GT(alive_threads_, 0); 2366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov alive_threads_--; 2376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_GT(running_threads_, 0); 2386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov running_threads_--; 2396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusRunning, tctx->status); 2436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetFinished(); 2446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->detached) { 2456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetDead(); 246ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov QuarantinePush(tctx); 2476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::StartThread(u32 tid, uptr os_id, void *arg) { 2516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov running_threads_++; 2536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusCreated, tctx->status); 2576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetStarted(os_id, arg); 2586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 260ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukovvoid ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) { 261ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov dead_threads_.push_back(tctx); 262ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov if (dead_threads_.size() <= thread_quarantine_size_) 263ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return; 264ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov tctx = dead_threads_.front(); 265ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov dead_threads_.pop_front(); 266ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov CHECK_EQ(tctx->status, ThreadStatusDead); 267ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov tctx->Reset(); 268ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov invalid_threads_.push_back(tctx); 269ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov} 270ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov 271ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry VyukovThreadContextBase *ThreadRegistry::QuarantinePop() { 272ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov if (invalid_threads_.size() == 0) 273ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return 0; 274ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov ThreadContextBase *tctx = invalid_threads_.front(); 275ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov invalid_threads_.pop_front(); 276ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return tctx; 277ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov} 278ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov 2796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} // namespace __sanitizer 280