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 void InitializeThreadRegistry() { 34 static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 35 thread_registry = 36 new (thread_registry_placeholder) ThreadRegistry(CreateThreadContext); 37 } 38 39 ThreadContextLsanBase::ThreadContextLsanBase(int tid) 40 : ThreadContextBase(tid) {} 41 42 void ThreadContextLsanBase::OnFinished() { 43 AllocatorThreadFinish(); 44 DTLS_Destroy(); 45 } 46 47 u32 ThreadCreate(u32 parent_tid, bool detached, void *arg) { 48 return thread_registry->CreateThread(0, detached, parent_tid, arg); 49 } 50 51 void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, 52 ThreadType thread_type, void *arg) { 53 thread_registry->StartThread(tid, os_id, thread_type, arg); 54 SetCurrentThread(tid); 55 } 56 57 void ThreadFinish() { 58 thread_registry->FinishThread(GetCurrentThread()); 59 SetCurrentThread(kInvalidTid); 60 } 61 62 ThreadContext *CurrentThreadContext() { 63 if (!thread_registry) 64 return nullptr; 65 if (GetCurrentThread() == kInvalidTid) 66 return nullptr; 67 // No lock needed when getting current thread. 68 return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread()); 69 } 70 71 void EnsureMainThreadIDIsCorrect() { 72 if (GetCurrentThread() == kMainTid) 73 CurrentThreadContext()->os_id = GetTid(); 74 } 75 76 ///// Interface to the common LSan module. ///// 77 78 void GetThreadExtraStackRangesLocked(tid_t os_id, 79 InternalMmapVector<Range> *ranges) {} 80 void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {} 81 82 void LockThreadRegistry() { thread_registry->Lock(); } 83 84 void UnlockThreadRegistry() { thread_registry->Unlock(); } 85 86 ThreadRegistry *GetLsanThreadRegistryLocked() { 87 thread_registry->CheckLocked(); 88 return thread_registry; 89 } 90 91 void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) { 92 GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( 93 [](ThreadContextBase *tctx, void *threads) { 94 if (tctx->status == ThreadStatusRunning) { 95 reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back( 96 tctx->os_id); 97 } 98 }, 99 threads); 100 } 101 102 } // namespace __lsan 103