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