168d75effSDimitry Andric //=-- lsan_thread.cpp -----------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of LeakSanitizer. 1068d75effSDimitry Andric // See lsan_thread.h for details. 1168d75effSDimitry Andric // 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "lsan_thread.h" 1568d75effSDimitry Andric 165ffd83dbSDimitry Andric #include "lsan.h" 175ffd83dbSDimitry Andric #include "lsan_allocator.h" 185ffd83dbSDimitry Andric #include "lsan_common.h" 1968d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h" 2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_placement_new.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_thread_registry.h" 2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_tls_get_addr.h" 2368d75effSDimitry Andric 2468d75effSDimitry Andric namespace __lsan { 2568d75effSDimitry Andric 2668d75effSDimitry Andric static ThreadRegistry *thread_registry; 2706c3fb27SDimitry Andric static ThreadArgRetval *thread_arg_retval; 2806c3fb27SDimitry Andric 2906c3fb27SDimitry Andric static Mutex mu_for_thread_context; 3006c3fb27SDimitry Andric static LowLevelAllocator allocator_for_thread_context; 3168d75effSDimitry Andric 3268d75effSDimitry Andric static ThreadContextBase *CreateThreadContext(u32 tid) { 3306c3fb27SDimitry Andric Lock lock(&mu_for_thread_context); 3406c3fb27SDimitry Andric return new (allocator_for_thread_context) ThreadContext(tid); 3568d75effSDimitry Andric } 3668d75effSDimitry Andric 3706c3fb27SDimitry Andric void InitializeThreads() { 38*0fca6ea1SDimitry Andric alignas(alignof(ThreadRegistry)) static char 39*0fca6ea1SDimitry Andric thread_registry_placeholder[sizeof(ThreadRegistry)]; 40fe6060f1SDimitry Andric thread_registry = 41fe6060f1SDimitry Andric new (thread_registry_placeholder) ThreadRegistry(CreateThreadContext); 4206c3fb27SDimitry Andric 43*0fca6ea1SDimitry Andric alignas(alignof(ThreadArgRetval)) static char 4406c3fb27SDimitry Andric thread_arg_retval_placeholder[sizeof(ThreadArgRetval)]; 4506c3fb27SDimitry Andric thread_arg_retval = new (thread_arg_retval_placeholder) ThreadArgRetval(); 4668d75effSDimitry Andric } 4768d75effSDimitry Andric 4806c3fb27SDimitry Andric ThreadArgRetval &GetThreadArgRetval() { return *thread_arg_retval; } 4906c3fb27SDimitry Andric 505ffd83dbSDimitry Andric ThreadContextLsanBase::ThreadContextLsanBase(int tid) 515ffd83dbSDimitry Andric : ThreadContextBase(tid) {} 5268d75effSDimitry Andric 5306c3fb27SDimitry Andric void ThreadContextLsanBase::OnStarted(void *arg) { 5406c3fb27SDimitry Andric SetCurrentThread(this); 5506c3fb27SDimitry Andric AllocatorThreadStart(); 5606c3fb27SDimitry Andric } 5706c3fb27SDimitry Andric 585ffd83dbSDimitry Andric void ThreadContextLsanBase::OnFinished() { 5968d75effSDimitry Andric AllocatorThreadFinish(); 6068d75effSDimitry Andric DTLS_Destroy(); 6106c3fb27SDimitry Andric SetCurrentThread(nullptr); 6268d75effSDimitry Andric } 6368d75effSDimitry Andric 64349cc55cSDimitry Andric u32 ThreadCreate(u32 parent_tid, bool detached, void *arg) { 65349cc55cSDimitry Andric return thread_registry->CreateThread(0, detached, parent_tid, arg); 6668d75effSDimitry Andric } 6768d75effSDimitry Andric 685ffd83dbSDimitry Andric void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, 695ffd83dbSDimitry Andric ThreadType thread_type, void *arg) { 705ffd83dbSDimitry Andric thread_registry->StartThread(tid, os_id, thread_type, arg); 7168d75effSDimitry Andric } 7268d75effSDimitry Andric 7306c3fb27SDimitry Andric void ThreadFinish() { thread_registry->FinishThread(GetCurrentThreadId()); } 7468d75effSDimitry Andric 7568d75effSDimitry Andric void EnsureMainThreadIDIsCorrect() { 7606c3fb27SDimitry Andric if (GetCurrentThreadId() == kMainTid) 7706c3fb27SDimitry Andric GetCurrentThread()->os_id = GetTid(); 7868d75effSDimitry Andric } 7968d75effSDimitry Andric 8068d75effSDimitry Andric ///// Interface to the common LSan module. ///// 8168d75effSDimitry Andric 82bdd1243dSDimitry Andric void GetThreadExtraStackRangesLocked(tid_t os_id, 83bdd1243dSDimitry Andric InternalMmapVector<Range> *ranges) {} 84bdd1243dSDimitry Andric void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {} 8568d75effSDimitry Andric 8606c3fb27SDimitry Andric void LockThreads() { 8706c3fb27SDimitry Andric thread_registry->Lock(); 8806c3fb27SDimitry Andric thread_arg_retval->Lock(); 8906c3fb27SDimitry Andric } 9068d75effSDimitry Andric 9106c3fb27SDimitry Andric void UnlockThreads() { 9206c3fb27SDimitry Andric thread_arg_retval->Unlock(); 9306c3fb27SDimitry Andric thread_registry->Unlock(); 9406c3fb27SDimitry Andric } 9568d75effSDimitry Andric 96bdd1243dSDimitry Andric ThreadRegistry *GetLsanThreadRegistryLocked() { 9768d75effSDimitry Andric thread_registry->CheckLocked(); 9868d75effSDimitry Andric return thread_registry; 9968d75effSDimitry Andric } 10068d75effSDimitry Andric 101bdd1243dSDimitry Andric void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) { 102bdd1243dSDimitry Andric GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( 103bdd1243dSDimitry Andric [](ThreadContextBase *tctx, void *threads) { 104bdd1243dSDimitry Andric if (tctx->status == ThreadStatusRunning) { 105bdd1243dSDimitry Andric reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back( 106bdd1243dSDimitry Andric tctx->os_id); 107bdd1243dSDimitry Andric } 108bdd1243dSDimitry Andric }, 109bdd1243dSDimitry Andric threads); 110bdd1243dSDimitry Andric } 111bdd1243dSDimitry Andric 11206c3fb27SDimitry Andric void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) { 11306c3fb27SDimitry Andric GetThreadArgRetval().GetAllPtrsLocked(ptrs); 11406c3fb27SDimitry Andric } 11506c3fb27SDimitry Andric 11668d75effSDimitry Andric } // namespace __lsan 117