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; 2768d75effSDimitry Andric 2868d75effSDimitry Andric static ThreadContextBase *CreateThreadContext(u32 tid) { 2968d75effSDimitry Andric void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); 3068d75effSDimitry Andric return new (mem) ThreadContext(tid); 3168d75effSDimitry Andric } 3268d75effSDimitry Andric 3368d75effSDimitry Andric void InitializeThreadRegistry() { 3468d75effSDimitry Andric static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 35*fe6060f1SDimitry Andric thread_registry = 36*fe6060f1SDimitry Andric new (thread_registry_placeholder) ThreadRegistry(CreateThreadContext); 3768d75effSDimitry Andric } 3868d75effSDimitry Andric 395ffd83dbSDimitry Andric ThreadContextLsanBase::ThreadContextLsanBase(int tid) 405ffd83dbSDimitry Andric : ThreadContextBase(tid) {} 4168d75effSDimitry Andric 425ffd83dbSDimitry Andric void ThreadContextLsanBase::OnFinished() { 4368d75effSDimitry Andric AllocatorThreadFinish(); 4468d75effSDimitry Andric DTLS_Destroy(); 4568d75effSDimitry Andric } 4668d75effSDimitry Andric 475ffd83dbSDimitry Andric u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached, void *arg) { 485ffd83dbSDimitry Andric return thread_registry->CreateThread(user_id, detached, parent_tid, arg); 4968d75effSDimitry Andric } 5068d75effSDimitry Andric 515ffd83dbSDimitry Andric void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, 525ffd83dbSDimitry Andric ThreadType thread_type, void *arg) { 535ffd83dbSDimitry Andric thread_registry->StartThread(tid, os_id, thread_type, arg); 545ffd83dbSDimitry Andric SetCurrentThread(tid); 5568d75effSDimitry Andric } 5668d75effSDimitry Andric 5768d75effSDimitry Andric void ThreadFinish() { 5868d75effSDimitry Andric thread_registry->FinishThread(GetCurrentThread()); 5968d75effSDimitry Andric SetCurrentThread(kInvalidTid); 6068d75effSDimitry Andric } 6168d75effSDimitry Andric 6268d75effSDimitry Andric ThreadContext *CurrentThreadContext() { 635ffd83dbSDimitry Andric if (!thread_registry) 645ffd83dbSDimitry Andric return nullptr; 6568d75effSDimitry Andric if (GetCurrentThread() == kInvalidTid) 6668d75effSDimitry Andric return nullptr; 6768d75effSDimitry Andric // No lock needed when getting current thread. 6868d75effSDimitry Andric return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread()); 6968d75effSDimitry Andric } 7068d75effSDimitry Andric 7168d75effSDimitry Andric static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) { 7268d75effSDimitry Andric uptr uid = (uptr)arg; 7368d75effSDimitry Andric if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) { 7468d75effSDimitry Andric return true; 7568d75effSDimitry Andric } 7668d75effSDimitry Andric return false; 7768d75effSDimitry Andric } 7868d75effSDimitry Andric 7968d75effSDimitry Andric u32 ThreadTid(uptr uid) { 8068d75effSDimitry Andric return thread_registry->FindThread(FindThreadByUid, (void *)uid); 8168d75effSDimitry Andric } 8268d75effSDimitry Andric 83e8d8bef9SDimitry Andric void ThreadDetach(u32 tid) { 84e8d8bef9SDimitry Andric CHECK_NE(tid, kInvalidTid); 85e8d8bef9SDimitry Andric thread_registry->DetachThread(tid, /* arg */ nullptr); 86e8d8bef9SDimitry Andric } 87e8d8bef9SDimitry Andric 8868d75effSDimitry Andric void ThreadJoin(u32 tid) { 8968d75effSDimitry Andric CHECK_NE(tid, kInvalidTid); 9068d75effSDimitry Andric thread_registry->JoinThread(tid, /* arg */ nullptr); 9168d75effSDimitry Andric } 9268d75effSDimitry Andric 9368d75effSDimitry Andric void EnsureMainThreadIDIsCorrect() { 94*fe6060f1SDimitry Andric if (GetCurrentThread() == kMainTid) 9568d75effSDimitry Andric CurrentThreadContext()->os_id = GetTid(); 9668d75effSDimitry Andric } 9768d75effSDimitry Andric 9868d75effSDimitry Andric ///// Interface to the common LSan module. ///// 9968d75effSDimitry Andric 10068d75effSDimitry Andric void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, 1015ffd83dbSDimitry Andric void *arg) {} 10268d75effSDimitry Andric 1035ffd83dbSDimitry Andric void LockThreadRegistry() { thread_registry->Lock(); } 10468d75effSDimitry Andric 1055ffd83dbSDimitry Andric void UnlockThreadRegistry() { thread_registry->Unlock(); } 10668d75effSDimitry Andric 10768d75effSDimitry Andric ThreadRegistry *GetThreadRegistryLocked() { 10868d75effSDimitry Andric thread_registry->CheckLocked(); 10968d75effSDimitry Andric return thread_registry; 11068d75effSDimitry Andric } 11168d75effSDimitry Andric 11268d75effSDimitry Andric } // namespace __lsan 113