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
CreateThreadContext(u32 tid)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
InitializeThreads()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
GetThreadArgRetval()4806c3fb27SDimitry Andric ThreadArgRetval &GetThreadArgRetval() { return *thread_arg_retval; }
4906c3fb27SDimitry Andric
ThreadContextLsanBase(int tid)505ffd83dbSDimitry Andric ThreadContextLsanBase::ThreadContextLsanBase(int tid)
515ffd83dbSDimitry Andric : ThreadContextBase(tid) {}
5268d75effSDimitry Andric
OnStarted(void * arg)5306c3fb27SDimitry Andric void ThreadContextLsanBase::OnStarted(void *arg) {
5406c3fb27SDimitry Andric SetCurrentThread(this);
5506c3fb27SDimitry Andric AllocatorThreadStart();
5606c3fb27SDimitry Andric }
5706c3fb27SDimitry Andric
OnFinished()585ffd83dbSDimitry Andric void ThreadContextLsanBase::OnFinished() {
5968d75effSDimitry Andric AllocatorThreadFinish();
6068d75effSDimitry Andric DTLS_Destroy();
6106c3fb27SDimitry Andric SetCurrentThread(nullptr);
6268d75effSDimitry Andric }
6368d75effSDimitry Andric
ThreadCreate(u32 parent_tid,bool detached,void * arg)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
ThreadStart(u32 tid,tid_t os_id,ThreadType thread_type,void * arg)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
ThreadFinish()7306c3fb27SDimitry Andric void ThreadFinish() { thread_registry->FinishThread(GetCurrentThreadId()); }
7468d75effSDimitry Andric
EnsureMainThreadIDIsCorrect()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
GetThreadExtraStackRangesLocked(tid_t os_id,InternalMmapVector<Range> * ranges)82bdd1243dSDimitry Andric void GetThreadExtraStackRangesLocked(tid_t os_id,
83bdd1243dSDimitry Andric InternalMmapVector<Range> *ranges) {}
GetThreadExtraStackRangesLocked(InternalMmapVector<Range> * ranges)84bdd1243dSDimitry Andric void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {}
8568d75effSDimitry Andric
LockThreads()8606c3fb27SDimitry Andric void LockThreads() {
8706c3fb27SDimitry Andric thread_registry->Lock();
8806c3fb27SDimitry Andric thread_arg_retval->Lock();
8906c3fb27SDimitry Andric }
9068d75effSDimitry Andric
UnlockThreads()9106c3fb27SDimitry Andric void UnlockThreads() {
9206c3fb27SDimitry Andric thread_arg_retval->Unlock();
9306c3fb27SDimitry Andric thread_registry->Unlock();
9406c3fb27SDimitry Andric }
9568d75effSDimitry Andric
GetLsanThreadRegistryLocked()96bdd1243dSDimitry Andric ThreadRegistry *GetLsanThreadRegistryLocked() {
9768d75effSDimitry Andric thread_registry->CheckLocked();
9868d75effSDimitry Andric return thread_registry;
9968d75effSDimitry Andric }
10068d75effSDimitry Andric
GetRunningThreadsLocked(InternalMmapVector<tid_t> * threads)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
GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> * ptrs)11206c3fb27SDimitry Andric void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {
11306c3fb27SDimitry Andric GetThreadArgRetval().GetAllPtrsLocked(ptrs);
11406c3fb27SDimitry Andric }
11506c3fb27SDimitry Andric
11668d75effSDimitry Andric } // namespace __lsan
117