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) 202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0), 212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines status(ThreadStatusInvalid), 222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines detached(false), parent_tid(0), next(0) { 236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name[0] = '\0'; 246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 266af642eaf764434ac6f28f242e7f081156bce9e3Dmitry VyukovThreadContextBase::~ThreadContextBase() { 27e374e4ece521692173aad355420d03e1b2cd819aAlexey Samsonov // ThreadContextBase should never be deleted. 286af642eaf764434ac6f28f242e7f081156bce9e3Dmitry Vyukov CHECK(0); 296af642eaf764434ac6f28f242e7f081156bce9e3Dmitry Vyukov} 30c7bc60cd4bfe21868aacd8a87b13590b314ed330Eric Christopher 316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetName(const char *new_name) { 326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name[0] = '\0'; 336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (new_name) { 346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov internal_strncpy(name, new_name, sizeof(name)); 356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov name[sizeof(name) - 1] = '\0'; 366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetDead() { 406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK(status == ThreadStatusRunning || 416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status == ThreadStatusFinished); 426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusDead; 436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov user_id = 0; 446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnDead(); 456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetJoined(void *arg) { 486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // FIXME(dvyukov): print message and continue (it's user error). 496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(false, detached); 506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusFinished, status); 516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusDead; 526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov user_id = 0; 536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnJoined(arg); 546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetFinished() { 576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (!detached) 586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusFinished; 596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnFinished(); 606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetStarted(uptr _os_id, void *arg) { 636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusRunning; 646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov os_id = _os_id; 656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnStarted(arg); 666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id, 696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov bool _detached, u32 _parent_tid, void *arg) { 706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusCreated; 716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov user_id = _user_id; 726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov unique_id = _unique_id; 736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov detached = _detached; 746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Parent tid makes no sense for the main thread. 756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tid != 0) 766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov parent_tid = _parent_tid; 776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov OnCreated(arg); 786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 80ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukovvoid ThreadContextBase::Reset() { 816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov status = ThreadStatusInvalid; 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, 912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u32 thread_quarantine_size, u32 max_reuse) 926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov : context_factory_(factory), 936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov max_threads_(max_threads), 946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov thread_quarantine_size_(thread_quarantine_size), 952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines max_reuse_(max_reuse), 966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov mtx_(), 976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov n_contexts_(0), 986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov total_threads_(0), 996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov alive_threads_(0), 1006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov max_alive_threads_(0), 1016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov running_threads_(0) { 1026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov threads_ = (ThreadContextBase **)MmapOrDie(max_threads_ * sizeof(threads_[0]), 1036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov "ThreadRegistry"); 1046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov dead_threads_.clear(); 105ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov invalid_threads_.clear(); 1066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running, 1096d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr *alive) { 1106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (total) *total = n_contexts_; 1126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (running) *running = running_threads_; 1136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (alive) *alive = alive_threads_; 1146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovuptr ThreadRegistry::GetMaxAliveThreads() { 1176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return max_alive_threads_; 1196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovu32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, 1226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void *arg) { 1236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov u32 tid = kUnknownTid; 125ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov ThreadContextBase *tctx = QuarantinePop(); 126ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov if (tctx) { 1276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tid = tctx->tid; 128ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov } else if (n_contexts_ < max_threads_) { 1296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Allocate new thread context and tid. 1306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tid = n_contexts_++; 1316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx = context_factory_(tid); 1326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov threads_[tid] = tctx; 133ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov } else { 1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifndef SANITIZER_GO 135ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov Report("%s: Thread limit (%u threads) exceeded. Dying.\n", 136ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov SanitizerToolName, max_threads_); 1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Printf("race: limit on %u simultaneously alive goroutines is exceeded," 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines " dying\n", max_threads_); 1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 141ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov Die(); 1426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 1446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tid, kUnknownTid); 1456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, max_threads_); 1466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(tctx->status, ThreadStatusInvalid); 1476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov alive_threads_++; 1486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (max_alive_threads_ < alive_threads_) { 1496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov max_alive_threads_++; 1506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(alive_threads_, max_alive_threads_); 1516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetCreated(user_id, total_threads_++, detached, 1536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov parent_tid, arg); 1546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tid; 1556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb, 1586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void *arg) { 1596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckLocked(); 1606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (u32 tid = 0; tid < n_contexts_; tid++) { 1616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx == 0) 1636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov continue; 1646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov cb(tctx, arg); 1656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovu32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) { 1696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 1706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (u32 tid = 0; tid < n_contexts_; tid++) { 1716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx != 0 && cb(tctx, arg)) 1736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tctx->tid; 1746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return kUnknownTid; 1766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovThreadContextBase * 1796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) { 1806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckLocked(); 1816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (u32 tid = 0; tid < n_contexts_; tid++) { 1826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 1836d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx != 0 && cb(tctx, arg)) 1846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tctx; 1856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return 0; 1876d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1886d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 18998d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveevstatic bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx, 19098d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev void *arg) { 19198d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid && 19298d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev tctx->status != ThreadStatusDead); 19398d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev} 19498d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev 19598d3b40ec5cf06e46397492c21acc9d18e8c54abSergey MatveevThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(uptr os_id) { 19698d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev return FindThreadContextLocked(FindThreadContextByOsIdCallback, 19798d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev (void *)os_id); 19898d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev} 19998d3b40ec5cf06e46397492c21acc9d18e8c54abSergey Matveev 2006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::SetThreadName(u32 tid, const char *name) { 2016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusRunning, tctx->status); 2066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetName(name); 2076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2095cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukovvoid ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) { 2105cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov BlockingMutexLock l(&mtx_); 2115cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov for (u32 tid = 0; tid < n_contexts_; tid++) { 2125cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov ThreadContextBase *tctx = threads_[tid]; 2135cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov if (tctx != 0 && tctx->user_id == user_id && 2145cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov tctx->status != ThreadStatusInvalid) { 2155cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov tctx->SetName(name); 2165cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov return; 2175cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov } 2185cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov } 2195cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov} 2205cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 2216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::DetachThread(u32 tid) { 2226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->status == ThreadStatusInvalid) { 2276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov Report("%s: Detach of non-existent thread\n", SanitizerToolName); 2286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return; 2296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->status == ThreadStatusFinished) { 2316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetDead(); 232ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov QuarantinePush(tctx); 2336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } else { 2346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->detached = true; 2356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::JoinThread(u32 tid, void *arg) { 2396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->status == ThreadStatusInvalid) { 2446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov Report("%s: Join of non-existent thread\n", SanitizerToolName); 2456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return; 2466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetJoined(arg); 248ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov QuarantinePush(tctx); 2496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::FinishThread(u32 tid) { 2526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_GT(alive_threads_, 0); 2546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov alive_threads_--; 2556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_GT(running_threads_, 0); 2566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov running_threads_--; 2576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusRunning, tctx->status); 2616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetFinished(); 2626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (tctx->detached) { 2636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetDead(); 264ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov QuarantinePush(tctx); 2656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid ThreadRegistry::StartThread(u32 tid, uptr os_id, void *arg) { 2696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&mtx_); 2706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov running_threads_++; 2716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_LT(tid, n_contexts_); 2726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *tctx = threads_[tid]; 2736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_NE(tctx, 0); 2746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CHECK_EQ(ThreadStatusCreated, tctx->status); 2756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tctx->SetStarted(os_id, arg); 2766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 278ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukovvoid ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) { 279ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov dead_threads_.push_back(tctx); 280ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov if (dead_threads_.size() <= thread_quarantine_size_) 281ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return; 282ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov tctx = dead_threads_.front(); 283ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov dead_threads_.pop_front(); 284ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov CHECK_EQ(tctx->status, ThreadStatusDead); 285ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov tctx->Reset(); 2862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines tctx->reuse_count++; 2872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (max_reuse_ > 0 && tctx->reuse_count >= max_reuse_) 2882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 289ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov invalid_threads_.push_back(tctx); 290ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov} 291ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov 292ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry VyukovThreadContextBase *ThreadRegistry::QuarantinePop() { 293ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov if (invalid_threads_.size() == 0) 294ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return 0; 295ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov ThreadContextBase *tctx = invalid_threads_.front(); 296ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov invalid_threads_.pop_front(); 297ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov return tctx; 298ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov} 299ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov 3006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} // namespace __sanitizer 301