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