Home | History | Annotate | Line # | Download | only in lsan
      1  1.1  joerg //=-- lsan_thread.cc ------------------------------------------------------===//
      2  1.1  joerg //
      3  1.1  joerg //                     The LLVM Compiler Infrastructure
      4  1.1  joerg //
      5  1.1  joerg // This file is distributed under the University of Illinois Open Source
      6  1.1  joerg // License. See LICENSE.TXT for details.
      7  1.1  joerg //
      8  1.1  joerg //===----------------------------------------------------------------------===//
      9  1.1  joerg //
     10  1.1  joerg // This file is a part of LeakSanitizer.
     11  1.1  joerg // See lsan_thread.h for details.
     12  1.1  joerg //
     13  1.1  joerg //===----------------------------------------------------------------------===//
     14  1.1  joerg 
     15  1.1  joerg #include "lsan_thread.h"
     16  1.1  joerg 
     17  1.1  joerg #include "sanitizer_common/sanitizer_common.h"
     18  1.1  joerg #include "sanitizer_common/sanitizer_placement_new.h"
     19  1.1  joerg #include "sanitizer_common/sanitizer_thread_registry.h"
     20  1.3  kamil #include "sanitizer_common/sanitizer_tls_get_addr.h"
     21  1.1  joerg #include "lsan_allocator.h"
     22  1.3  kamil #include "lsan_common.h"
     23  1.1  joerg 
     24  1.1  joerg namespace __lsan {
     25  1.1  joerg 
     26  1.1  joerg static ThreadRegistry *thread_registry;
     27  1.1  joerg 
     28  1.1  joerg static ThreadContextBase *CreateThreadContext(u32 tid) {
     29  1.1  joerg   void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext");
     30  1.1  joerg   return new(mem) ThreadContext(tid);
     31  1.1  joerg }
     32  1.1  joerg 
     33  1.1  joerg static const uptr kMaxThreads = 1 << 13;
     34  1.1  joerg static const uptr kThreadQuarantineSize = 64;
     35  1.1  joerg 
     36  1.1  joerg void InitializeThreadRegistry() {
     37  1.3  kamil   static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)];
     38  1.1  joerg   thread_registry = new(thread_registry_placeholder)
     39  1.1  joerg     ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize);
     40  1.1  joerg }
     41  1.1  joerg 
     42  1.1  joerg ThreadContext::ThreadContext(int tid)
     43  1.3  kamil     : ThreadContextBase(tid),
     44  1.3  kamil       stack_begin_(0),
     45  1.3  kamil       stack_end_(0),
     46  1.3  kamil       cache_begin_(0),
     47  1.3  kamil       cache_end_(0),
     48  1.3  kamil       tls_begin_(0),
     49  1.3  kamil       tls_end_(0),
     50  1.3  kamil       dtls_(nullptr) {}
     51  1.1  joerg 
     52  1.1  joerg struct OnStartedArgs {
     53  1.1  joerg   uptr stack_begin, stack_end,
     54  1.1  joerg        cache_begin, cache_end,
     55  1.1  joerg        tls_begin, tls_end;
     56  1.3  kamil   DTLS *dtls;
     57  1.1  joerg };
     58  1.1  joerg 
     59  1.1  joerg void ThreadContext::OnStarted(void *arg) {
     60  1.1  joerg   OnStartedArgs *args = reinterpret_cast<OnStartedArgs *>(arg);
     61  1.1  joerg   stack_begin_ = args->stack_begin;
     62  1.1  joerg   stack_end_ = args->stack_end;
     63  1.1  joerg   tls_begin_ = args->tls_begin;
     64  1.1  joerg   tls_end_ = args->tls_end;
     65  1.1  joerg   cache_begin_ = args->cache_begin;
     66  1.1  joerg   cache_end_ = args->cache_end;
     67  1.3  kamil   dtls_ = args->dtls;
     68  1.1  joerg }
     69  1.1  joerg 
     70  1.1  joerg void ThreadContext::OnFinished() {
     71  1.1  joerg   AllocatorThreadFinish();
     72  1.3  kamil   DTLS_Destroy();
     73  1.1  joerg }
     74  1.1  joerg 
     75  1.1  joerg u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) {
     76  1.1  joerg   return thread_registry->CreateThread(user_id, detached, parent_tid,
     77  1.3  kamil                                        /* arg */ nullptr);
     78  1.1  joerg }
     79  1.1  joerg 
     80  1.3  kamil void ThreadStart(u32 tid, tid_t os_id, bool workerthread) {
     81  1.1  joerg   OnStartedArgs args;
     82  1.1  joerg   uptr stack_size = 0;
     83  1.1  joerg   uptr tls_size = 0;
     84  1.1  joerg   GetThreadStackAndTls(tid == 0, &args.stack_begin, &stack_size,
     85  1.1  joerg                        &args.tls_begin, &tls_size);
     86  1.1  joerg   args.stack_end = args.stack_begin + stack_size;
     87  1.1  joerg   args.tls_end = args.tls_begin + tls_size;
     88  1.1  joerg   GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
     89  1.3  kamil   args.dtls = DTLS_Get();
     90  1.3  kamil   thread_registry->StartThread(tid, os_id, workerthread, &args);
     91  1.1  joerg }
     92  1.1  joerg 
     93  1.1  joerg void ThreadFinish() {
     94  1.1  joerg   thread_registry->FinishThread(GetCurrentThread());
     95  1.3  kamil   SetCurrentThread(kInvalidTid);
     96  1.1  joerg }
     97  1.1  joerg 
     98  1.1  joerg ThreadContext *CurrentThreadContext() {
     99  1.3  kamil   if (!thread_registry) return nullptr;
    100  1.1  joerg   if (GetCurrentThread() == kInvalidTid)
    101  1.3  kamil     return nullptr;
    102  1.1  joerg   // No lock needed when getting current thread.
    103  1.1  joerg   return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread());
    104  1.1  joerg }
    105  1.1  joerg 
    106  1.1  joerg static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) {
    107  1.1  joerg   uptr uid = (uptr)arg;
    108  1.1  joerg   if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) {
    109  1.1  joerg     return true;
    110  1.1  joerg   }
    111  1.1  joerg   return false;
    112  1.1  joerg }
    113  1.1  joerg 
    114  1.1  joerg u32 ThreadTid(uptr uid) {
    115  1.1  joerg   return thread_registry->FindThread(FindThreadByUid, (void*)uid);
    116  1.1  joerg }
    117  1.1  joerg 
    118  1.1  joerg void ThreadJoin(u32 tid) {
    119  1.1  joerg   CHECK_NE(tid, kInvalidTid);
    120  1.3  kamil   thread_registry->JoinThread(tid, /* arg */nullptr);
    121  1.3  kamil }
    122  1.3  kamil 
    123  1.3  kamil void EnsureMainThreadIDIsCorrect() {
    124  1.3  kamil   if (GetCurrentThread() == 0)
    125  1.3  kamil     CurrentThreadContext()->os_id = GetTid();
    126  1.1  joerg }
    127  1.1  joerg 
    128  1.1  joerg ///// Interface to the common LSan module. /////
    129  1.1  joerg 
    130  1.3  kamil bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
    131  1.3  kamil                            uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
    132  1.3  kamil                            uptr *cache_end, DTLS **dtls) {
    133  1.1  joerg   ThreadContext *context = static_cast<ThreadContext *>(
    134  1.1  joerg       thread_registry->FindThreadContextByOsIDLocked(os_id));
    135  1.1  joerg   if (!context) return false;
    136  1.1  joerg   *stack_begin = context->stack_begin();
    137  1.1  joerg   *stack_end = context->stack_end();
    138  1.1  joerg   *tls_begin = context->tls_begin();
    139  1.1  joerg   *tls_end = context->tls_end();
    140  1.1  joerg   *cache_begin = context->cache_begin();
    141  1.1  joerg   *cache_end = context->cache_end();
    142  1.3  kamil   *dtls = context->dtls();
    143  1.1  joerg   return true;
    144  1.1  joerg }
    145  1.1  joerg 
    146  1.3  kamil void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback,
    147  1.3  kamil                             void *arg) {
    148  1.3  kamil }
    149  1.3  kamil 
    150  1.1  joerg void LockThreadRegistry() {
    151  1.1  joerg   thread_registry->Lock();
    152  1.1  joerg }
    153  1.1  joerg 
    154  1.1  joerg void UnlockThreadRegistry() {
    155  1.1  joerg   thread_registry->Unlock();
    156  1.1  joerg }
    157  1.1  joerg 
    158  1.3  kamil ThreadRegistry *GetThreadRegistryLocked() {
    159  1.3  kamil   thread_registry->CheckLocked();
    160  1.3  kamil   return thread_registry;
    161  1.3  kamil }
    162  1.3  kamil 
    163  1.3  kamil } // namespace __lsan
    164