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