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