1 //=-- lsan_thread.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of LeakSanitizer. 10 // See lsan_thread.h for details. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "lsan_thread.h" 15 16 #include "lsan.h" 17 #include "lsan_allocator.h" 18 #include "lsan_common.h" 19 #include "sanitizer_common/sanitizer_common.h" 20 #include "sanitizer_common/sanitizer_placement_new.h" 21 #include "sanitizer_common/sanitizer_thread_registry.h" 22 #include "sanitizer_common/sanitizer_tls_get_addr.h" 23 24 namespace __lsan { 25 26 static ThreadRegistry *thread_registry; 27 28 static ThreadContextBase *CreateThreadContext(u32 tid) { 29 void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); 30 return new (mem) ThreadContext(tid); 31 } 32 33 static const uptr kMaxThreads = 1 << 13; 34 static const uptr kThreadQuarantineSize = 64; 35 36 void InitializeThreadRegistry() { 37 static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 38 thread_registry = new (thread_registry_placeholder) 39 ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize); 40 } 41 42 ThreadContextLsanBase::ThreadContextLsanBase(int tid) 43 : ThreadContextBase(tid) {} 44 45 void ThreadContextLsanBase::OnFinished() { 46 AllocatorThreadFinish(); 47 DTLS_Destroy(); 48 } 49 50 u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached, void *arg) { 51 return thread_registry->CreateThread(user_id, detached, parent_tid, arg); 52 } 53 54 void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, 55 ThreadType thread_type, void *arg) { 56 thread_registry->StartThread(tid, os_id, thread_type, arg); 57 SetCurrentThread(tid); 58 } 59 60 void ThreadFinish() { 61 thread_registry->FinishThread(GetCurrentThread()); 62 SetCurrentThread(kInvalidTid); 63 } 64 65 ThreadContext *CurrentThreadContext() { 66 if (!thread_registry) 67 return nullptr; 68 if (GetCurrentThread() == kInvalidTid) 69 return nullptr; 70 // No lock needed when getting current thread. 71 return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread()); 72 } 73 74 static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) { 75 uptr uid = (uptr)arg; 76 if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) { 77 return true; 78 } 79 return false; 80 } 81 82 u32 ThreadTid(uptr uid) { 83 return thread_registry->FindThread(FindThreadByUid, (void *)uid); 84 } 85 86 void ThreadDetach(u32 tid) { 87 CHECK_NE(tid, kInvalidTid); 88 thread_registry->DetachThread(tid, /* arg */ nullptr); 89 } 90 91 void ThreadJoin(u32 tid) { 92 CHECK_NE(tid, kInvalidTid); 93 thread_registry->JoinThread(tid, /* arg */ nullptr); 94 } 95 96 void EnsureMainThreadIDIsCorrect() { 97 if (GetCurrentThread() == 0) 98 CurrentThreadContext()->os_id = GetTid(); 99 } 100 101 ///// Interface to the common LSan module. ///// 102 103 void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, 104 void *arg) {} 105 106 void LockThreadRegistry() { thread_registry->Lock(); } 107 108 void UnlockThreadRegistry() { thread_registry->Unlock(); } 109 110 ThreadRegistry *GetThreadRegistryLocked() { 111 thread_registry->CheckLocked(); 112 return thread_registry; 113 } 114 115 } // namespace __lsan 116