13cab2bb3Spatrick //=-- lsan_thread.cpp -----------------------------------------------------===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // 93cab2bb3Spatrick // This file is a part of LeakSanitizer. 103cab2bb3Spatrick // See lsan_thread.h for details. 113cab2bb3Spatrick // 123cab2bb3Spatrick //===----------------------------------------------------------------------===// 133cab2bb3Spatrick 143cab2bb3Spatrick #include "lsan_thread.h" 153cab2bb3Spatrick 161f9cb04fSpatrick #include "lsan.h" 171f9cb04fSpatrick #include "lsan_allocator.h" 181f9cb04fSpatrick #include "lsan_common.h" 193cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h" 203cab2bb3Spatrick #include "sanitizer_common/sanitizer_placement_new.h" 213cab2bb3Spatrick #include "sanitizer_common/sanitizer_thread_registry.h" 223cab2bb3Spatrick #include "sanitizer_common/sanitizer_tls_get_addr.h" 233cab2bb3Spatrick 243cab2bb3Spatrick namespace __lsan { 253cab2bb3Spatrick 263cab2bb3Spatrick static ThreadRegistry *thread_registry; 273cab2bb3Spatrick 283cab2bb3Spatrick static ThreadContextBase *CreateThreadContext(u32 tid) { 293cab2bb3Spatrick void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); 303cab2bb3Spatrick return new (mem) ThreadContext(tid); 313cab2bb3Spatrick } 323cab2bb3Spatrick 333cab2bb3Spatrick void InitializeThreadRegistry() { 343cab2bb3Spatrick static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 35*d89ec533Spatrick thread_registry = 36*d89ec533Spatrick new (thread_registry_placeholder) ThreadRegistry(CreateThreadContext); 373cab2bb3Spatrick } 383cab2bb3Spatrick 391f9cb04fSpatrick ThreadContextLsanBase::ThreadContextLsanBase(int tid) 401f9cb04fSpatrick : ThreadContextBase(tid) {} 413cab2bb3Spatrick 421f9cb04fSpatrick void ThreadContextLsanBase::OnFinished() { 433cab2bb3Spatrick AllocatorThreadFinish(); 443cab2bb3Spatrick DTLS_Destroy(); 453cab2bb3Spatrick } 463cab2bb3Spatrick 471f9cb04fSpatrick u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached, void *arg) { 481f9cb04fSpatrick return thread_registry->CreateThread(user_id, detached, parent_tid, arg); 493cab2bb3Spatrick } 503cab2bb3Spatrick 511f9cb04fSpatrick void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, 521f9cb04fSpatrick ThreadType thread_type, void *arg) { 531f9cb04fSpatrick thread_registry->StartThread(tid, os_id, thread_type, arg); 541f9cb04fSpatrick SetCurrentThread(tid); 553cab2bb3Spatrick } 563cab2bb3Spatrick 573cab2bb3Spatrick void ThreadFinish() { 583cab2bb3Spatrick thread_registry->FinishThread(GetCurrentThread()); 593cab2bb3Spatrick SetCurrentThread(kInvalidTid); 603cab2bb3Spatrick } 613cab2bb3Spatrick 623cab2bb3Spatrick ThreadContext *CurrentThreadContext() { 631f9cb04fSpatrick if (!thread_registry) 641f9cb04fSpatrick return nullptr; 653cab2bb3Spatrick if (GetCurrentThread() == kInvalidTid) 663cab2bb3Spatrick return nullptr; 673cab2bb3Spatrick // No lock needed when getting current thread. 683cab2bb3Spatrick return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread()); 693cab2bb3Spatrick } 703cab2bb3Spatrick 713cab2bb3Spatrick static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) { 723cab2bb3Spatrick uptr uid = (uptr)arg; 733cab2bb3Spatrick if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) { 743cab2bb3Spatrick return true; 753cab2bb3Spatrick } 763cab2bb3Spatrick return false; 773cab2bb3Spatrick } 783cab2bb3Spatrick 793cab2bb3Spatrick u32 ThreadTid(uptr uid) { 803cab2bb3Spatrick return thread_registry->FindThread(FindThreadByUid, (void *)uid); 813cab2bb3Spatrick } 823cab2bb3Spatrick 83*d89ec533Spatrick void ThreadDetach(u32 tid) { 84*d89ec533Spatrick CHECK_NE(tid, kInvalidTid); 85*d89ec533Spatrick thread_registry->DetachThread(tid, /* arg */ nullptr); 86*d89ec533Spatrick } 87*d89ec533Spatrick 883cab2bb3Spatrick void ThreadJoin(u32 tid) { 893cab2bb3Spatrick CHECK_NE(tid, kInvalidTid); 903cab2bb3Spatrick thread_registry->JoinThread(tid, /* arg */ nullptr); 913cab2bb3Spatrick } 923cab2bb3Spatrick 933cab2bb3Spatrick void EnsureMainThreadIDIsCorrect() { 94*d89ec533Spatrick if (GetCurrentThread() == kMainTid) 953cab2bb3Spatrick CurrentThreadContext()->os_id = GetTid(); 963cab2bb3Spatrick } 973cab2bb3Spatrick 983cab2bb3Spatrick ///// Interface to the common LSan module. ///// 993cab2bb3Spatrick 1003cab2bb3Spatrick void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, 1011f9cb04fSpatrick void *arg) {} 1023cab2bb3Spatrick 1031f9cb04fSpatrick void LockThreadRegistry() { thread_registry->Lock(); } 1043cab2bb3Spatrick 1051f9cb04fSpatrick void UnlockThreadRegistry() { thread_registry->Unlock(); } 1063cab2bb3Spatrick 1073cab2bb3Spatrick ThreadRegistry *GetThreadRegistryLocked() { 1083cab2bb3Spatrick thread_registry->CheckLocked(); 1093cab2bb3Spatrick return thread_registry; 1103cab2bb3Spatrick } 1113cab2bb3Spatrick 1123cab2bb3Spatrick } // namespace __lsan 113