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 static ThreadArgRetval *thread_arg_retval; 28 29 static Mutex mu_for_thread_context; 30 static LowLevelAllocator allocator_for_thread_context; 31 32 static ThreadContextBase *CreateThreadContext(u32 tid) { 33 Lock lock(&mu_for_thread_context); 34 return new (allocator_for_thread_context) ThreadContext(tid); 35 } 36 37 void InitializeThreads() { 38 static ALIGNED(alignof( 39 ThreadRegistry)) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 40 thread_registry = 41 new (thread_registry_placeholder) ThreadRegistry(CreateThreadContext); 42 43 static ALIGNED(alignof(ThreadArgRetval)) char 44 thread_arg_retval_placeholder[sizeof(ThreadArgRetval)]; 45 thread_arg_retval = new (thread_arg_retval_placeholder) ThreadArgRetval(); 46 } 47 48 ThreadArgRetval &GetThreadArgRetval() { return *thread_arg_retval; } 49 50 ThreadContextLsanBase::ThreadContextLsanBase(int tid) 51 : ThreadContextBase(tid) {} 52 53 void ThreadContextLsanBase::OnStarted(void *arg) { 54 SetCurrentThread(this); 55 AllocatorThreadStart(); 56 } 57 58 void ThreadContextLsanBase::OnFinished() { 59 AllocatorThreadFinish(); 60 DTLS_Destroy(); 61 SetCurrentThread(nullptr); 62 } 63 64 u32 ThreadCreate(u32 parent_tid, bool detached, void *arg) { 65 return thread_registry->CreateThread(0, detached, parent_tid, arg); 66 } 67 68 void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, 69 ThreadType thread_type, void *arg) { 70 thread_registry->StartThread(tid, os_id, thread_type, arg); 71 } 72 73 void ThreadFinish() { thread_registry->FinishThread(GetCurrentThreadId()); } 74 75 void EnsureMainThreadIDIsCorrect() { 76 if (GetCurrentThreadId() == kMainTid) 77 GetCurrentThread()->os_id = GetTid(); 78 } 79 80 ///// Interface to the common LSan module. ///// 81 82 void GetThreadExtraStackRangesLocked(tid_t os_id, 83 InternalMmapVector<Range> *ranges) {} 84 void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {} 85 86 void LockThreads() { 87 thread_registry->Lock(); 88 thread_arg_retval->Lock(); 89 } 90 91 void UnlockThreads() { 92 thread_arg_retval->Unlock(); 93 thread_registry->Unlock(); 94 } 95 96 ThreadRegistry *GetLsanThreadRegistryLocked() { 97 thread_registry->CheckLocked(); 98 return thread_registry; 99 } 100 101 void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) { 102 GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( 103 [](ThreadContextBase *tctx, void *threads) { 104 if (tctx->status == ThreadStatusRunning) { 105 reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back( 106 tctx->os_id); 107 } 108 }, 109 threads); 110 } 111 112 void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) { 113 GetThreadArgRetval().GetAllPtrsLocked(ptrs); 114 } 115 116 } // namespace __lsan 117