1 1.1 joerg //=-- lsan_thread.cc ------------------------------------------------------===// 2 1.1 joerg // 3 1.1 joerg // The LLVM Compiler Infrastructure 4 1.1 joerg // 5 1.1 joerg // This file is distributed under the University of Illinois Open Source 6 1.1 joerg // License. See LICENSE.TXT for details. 7 1.1 joerg // 8 1.1 joerg //===----------------------------------------------------------------------===// 9 1.1 joerg // 10 1.1 joerg // This file is a part of LeakSanitizer. 11 1.1 joerg // See lsan_thread.h for details. 12 1.1 joerg // 13 1.1 joerg //===----------------------------------------------------------------------===// 14 1.1 joerg 15 1.1 joerg #include "lsan_thread.h" 16 1.1 joerg 17 1.1 joerg #include "sanitizer_common/sanitizer_common.h" 18 1.1 joerg #include "sanitizer_common/sanitizer_placement_new.h" 19 1.1 joerg #include "sanitizer_common/sanitizer_thread_registry.h" 20 1.3 kamil #include "sanitizer_common/sanitizer_tls_get_addr.h" 21 1.1 joerg #include "lsan_allocator.h" 22 1.3 kamil #include "lsan_common.h" 23 1.1 joerg 24 1.1 joerg namespace __lsan { 25 1.1 joerg 26 1.1 joerg static ThreadRegistry *thread_registry; 27 1.1 joerg 28 1.1 joerg static ThreadContextBase *CreateThreadContext(u32 tid) { 29 1.1 joerg void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); 30 1.1 joerg return new(mem) ThreadContext(tid); 31 1.1 joerg } 32 1.1 joerg 33 1.1 joerg static const uptr kMaxThreads = 1 << 13; 34 1.1 joerg static const uptr kThreadQuarantineSize = 64; 35 1.1 joerg 36 1.1 joerg void InitializeThreadRegistry() { 37 1.3 kamil static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 38 1.1 joerg thread_registry = new(thread_registry_placeholder) 39 1.1 joerg ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize); 40 1.1 joerg } 41 1.1 joerg 42 1.1 joerg ThreadContext::ThreadContext(int tid) 43 1.3 kamil : ThreadContextBase(tid), 44 1.3 kamil stack_begin_(0), 45 1.3 kamil stack_end_(0), 46 1.3 kamil cache_begin_(0), 47 1.3 kamil cache_end_(0), 48 1.3 kamil tls_begin_(0), 49 1.3 kamil tls_end_(0), 50 1.3 kamil dtls_(nullptr) {} 51 1.1 joerg 52 1.1 joerg struct OnStartedArgs { 53 1.1 joerg uptr stack_begin, stack_end, 54 1.1 joerg cache_begin, cache_end, 55 1.1 joerg tls_begin, tls_end; 56 1.3 kamil DTLS *dtls; 57 1.1 joerg }; 58 1.1 joerg 59 1.1 joerg void ThreadContext::OnStarted(void *arg) { 60 1.1 joerg OnStartedArgs *args = reinterpret_cast<OnStartedArgs *>(arg); 61 1.1 joerg stack_begin_ = args->stack_begin; 62 1.1 joerg stack_end_ = args->stack_end; 63 1.1 joerg tls_begin_ = args->tls_begin; 64 1.1 joerg tls_end_ = args->tls_end; 65 1.1 joerg cache_begin_ = args->cache_begin; 66 1.1 joerg cache_end_ = args->cache_end; 67 1.3 kamil dtls_ = args->dtls; 68 1.1 joerg } 69 1.1 joerg 70 1.1 joerg void ThreadContext::OnFinished() { 71 1.1 joerg AllocatorThreadFinish(); 72 1.3 kamil DTLS_Destroy(); 73 1.1 joerg } 74 1.1 joerg 75 1.1 joerg u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) { 76 1.1 joerg return thread_registry->CreateThread(user_id, detached, parent_tid, 77 1.3 kamil /* arg */ nullptr); 78 1.1 joerg } 79 1.1 joerg 80 1.3 kamil void ThreadStart(u32 tid, tid_t os_id, bool workerthread) { 81 1.1 joerg OnStartedArgs args; 82 1.1 joerg uptr stack_size = 0; 83 1.1 joerg uptr tls_size = 0; 84 1.1 joerg GetThreadStackAndTls(tid == 0, &args.stack_begin, &stack_size, 85 1.1 joerg &args.tls_begin, &tls_size); 86 1.1 joerg args.stack_end = args.stack_begin + stack_size; 87 1.1 joerg args.tls_end = args.tls_begin + tls_size; 88 1.1 joerg GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); 89 1.3 kamil args.dtls = DTLS_Get(); 90 1.3 kamil thread_registry->StartThread(tid, os_id, workerthread, &args); 91 1.1 joerg } 92 1.1 joerg 93 1.1 joerg void ThreadFinish() { 94 1.1 joerg thread_registry->FinishThread(GetCurrentThread()); 95 1.3 kamil SetCurrentThread(kInvalidTid); 96 1.1 joerg } 97 1.1 joerg 98 1.1 joerg ThreadContext *CurrentThreadContext() { 99 1.3 kamil if (!thread_registry) return nullptr; 100 1.1 joerg if (GetCurrentThread() == kInvalidTid) 101 1.3 kamil return nullptr; 102 1.1 joerg // No lock needed when getting current thread. 103 1.1 joerg return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread()); 104 1.1 joerg } 105 1.1 joerg 106 1.1 joerg static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) { 107 1.1 joerg uptr uid = (uptr)arg; 108 1.1 joerg if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) { 109 1.1 joerg return true; 110 1.1 joerg } 111 1.1 joerg return false; 112 1.1 joerg } 113 1.1 joerg 114 1.1 joerg u32 ThreadTid(uptr uid) { 115 1.1 joerg return thread_registry->FindThread(FindThreadByUid, (void*)uid); 116 1.1 joerg } 117 1.1 joerg 118 1.1 joerg void ThreadJoin(u32 tid) { 119 1.1 joerg CHECK_NE(tid, kInvalidTid); 120 1.3 kamil thread_registry->JoinThread(tid, /* arg */nullptr); 121 1.3 kamil } 122 1.3 kamil 123 1.3 kamil void EnsureMainThreadIDIsCorrect() { 124 1.3 kamil if (GetCurrentThread() == 0) 125 1.3 kamil CurrentThreadContext()->os_id = GetTid(); 126 1.1 joerg } 127 1.1 joerg 128 1.1 joerg ///// Interface to the common LSan module. ///// 129 1.1 joerg 130 1.3 kamil bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, 131 1.3 kamil uptr *tls_begin, uptr *tls_end, uptr *cache_begin, 132 1.3 kamil uptr *cache_end, DTLS **dtls) { 133 1.1 joerg ThreadContext *context = static_cast<ThreadContext *>( 134 1.1 joerg thread_registry->FindThreadContextByOsIDLocked(os_id)); 135 1.1 joerg if (!context) return false; 136 1.1 joerg *stack_begin = context->stack_begin(); 137 1.1 joerg *stack_end = context->stack_end(); 138 1.1 joerg *tls_begin = context->tls_begin(); 139 1.1 joerg *tls_end = context->tls_end(); 140 1.1 joerg *cache_begin = context->cache_begin(); 141 1.1 joerg *cache_end = context->cache_end(); 142 1.3 kamil *dtls = context->dtls(); 143 1.1 joerg return true; 144 1.1 joerg } 145 1.1 joerg 146 1.3 kamil void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, 147 1.3 kamil void *arg) { 148 1.3 kamil } 149 1.3 kamil 150 1.1 joerg void LockThreadRegistry() { 151 1.1 joerg thread_registry->Lock(); 152 1.1 joerg } 153 1.1 joerg 154 1.1 joerg void UnlockThreadRegistry() { 155 1.1 joerg thread_registry->Unlock(); 156 1.1 joerg } 157 1.1 joerg 158 1.3 kamil ThreadRegistry *GetThreadRegistryLocked() { 159 1.3 kamil thread_registry->CheckLocked(); 160 1.3 kamil return thread_registry; 161 1.3 kamil } 162 1.3 kamil 163 1.3 kamil } // namespace __lsan 164