xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/lsan/lsan_thread.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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