1*e8d8bef9SDimitry Andric //===-- memprof_thread.h ---------------------------------------*- C++ -*-===// 2*e8d8bef9SDimitry Andric // 3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e8d8bef9SDimitry Andric // 7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8*e8d8bef9SDimitry Andric // 9*e8d8bef9SDimitry Andric // This file is a part of MemProfiler, a memory profiler. 10*e8d8bef9SDimitry Andric // 11*e8d8bef9SDimitry Andric // MemProf-private header for memprof_thread.cpp. 12*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 13*e8d8bef9SDimitry Andric 14*e8d8bef9SDimitry Andric #ifndef MEMPROF_THREAD_H 15*e8d8bef9SDimitry Andric #define MEMPROF_THREAD_H 16*e8d8bef9SDimitry Andric 17*e8d8bef9SDimitry Andric #include "memprof_allocator.h" 18*e8d8bef9SDimitry Andric #include "memprof_internal.h" 19*e8d8bef9SDimitry Andric #include "memprof_stats.h" 20*e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_common.h" 21*e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 22*e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_thread_registry.h" 23*e8d8bef9SDimitry Andric 24*e8d8bef9SDimitry Andric namespace __sanitizer { 25*e8d8bef9SDimitry Andric struct DTLS; 26*e8d8bef9SDimitry Andric } // namespace __sanitizer 27*e8d8bef9SDimitry Andric 28*e8d8bef9SDimitry Andric namespace __memprof { 29*e8d8bef9SDimitry Andric 30*e8d8bef9SDimitry Andric class MemprofThread; 31*e8d8bef9SDimitry Andric 32*e8d8bef9SDimitry Andric // These objects are created for every thread and are never deleted, 33*e8d8bef9SDimitry Andric // so we can find them by tid even if the thread is long dead. 34*e8d8bef9SDimitry Andric struct MemprofThreadContext final : public ThreadContextBase { MemprofThreadContextfinal35*e8d8bef9SDimitry Andric explicit MemprofThreadContext(int tid) 36*e8d8bef9SDimitry Andric : ThreadContextBase(tid), announced(false), 37*e8d8bef9SDimitry Andric destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), 38*e8d8bef9SDimitry Andric thread(nullptr) {} 39*e8d8bef9SDimitry Andric bool announced; 40*e8d8bef9SDimitry Andric u8 destructor_iterations; 41*e8d8bef9SDimitry Andric u32 stack_id; 42*e8d8bef9SDimitry Andric MemprofThread *thread; 43*e8d8bef9SDimitry Andric 44*e8d8bef9SDimitry Andric void OnCreated(void *arg) override; 45*e8d8bef9SDimitry Andric void OnFinished() override; 46*e8d8bef9SDimitry Andric 47*e8d8bef9SDimitry Andric struct CreateThreadContextArgs { 48*e8d8bef9SDimitry Andric MemprofThread *thread; 49*e8d8bef9SDimitry Andric StackTrace *stack; 50*e8d8bef9SDimitry Andric }; 51*e8d8bef9SDimitry Andric }; 52*e8d8bef9SDimitry Andric 53*e8d8bef9SDimitry Andric // MemprofThreadContext objects are never freed, so we need many of them. 54*e8d8bef9SDimitry Andric COMPILER_CHECK(sizeof(MemprofThreadContext) <= 256); 55*e8d8bef9SDimitry Andric 56*e8d8bef9SDimitry Andric // MemprofThread are stored in TSD and destroyed when the thread dies. 57*e8d8bef9SDimitry Andric class MemprofThread { 58*e8d8bef9SDimitry Andric public: 59*e8d8bef9SDimitry Andric static MemprofThread *Create(thread_callback_t start_routine, void *arg, 60*e8d8bef9SDimitry Andric u32 parent_tid, StackTrace *stack, 61*e8d8bef9SDimitry Andric bool detached); 62*e8d8bef9SDimitry Andric static void TSDDtor(void *tsd); 63*e8d8bef9SDimitry Andric void Destroy(); 64*e8d8bef9SDimitry Andric 65*e8d8bef9SDimitry Andric struct InitOptions; 66*e8d8bef9SDimitry Andric void Init(const InitOptions *options = nullptr); 67*e8d8bef9SDimitry Andric 68*e8d8bef9SDimitry Andric thread_return_t ThreadStart(tid_t os_id, 69*e8d8bef9SDimitry Andric atomic_uintptr_t *signal_thread_is_registered); 70*e8d8bef9SDimitry Andric 71*e8d8bef9SDimitry Andric uptr stack_top(); 72*e8d8bef9SDimitry Andric uptr stack_bottom(); 73*e8d8bef9SDimitry Andric uptr stack_size(); tls_begin()74*e8d8bef9SDimitry Andric uptr tls_begin() { return tls_begin_; } tls_end()75*e8d8bef9SDimitry Andric uptr tls_end() { return tls_end_; } dtls()76*e8d8bef9SDimitry Andric DTLS *dtls() { return dtls_; } tid()77*e8d8bef9SDimitry Andric u32 tid() { return context_->tid; } context()78*e8d8bef9SDimitry Andric MemprofThreadContext *context() { return context_; } set_context(MemprofThreadContext * context)79*e8d8bef9SDimitry Andric void set_context(MemprofThreadContext *context) { context_ = context; } 80*e8d8bef9SDimitry Andric 81*e8d8bef9SDimitry Andric bool AddrIsInStack(uptr addr); 82*e8d8bef9SDimitry Andric 83*e8d8bef9SDimitry Andric // True is this thread is currently unwinding stack (i.e. collecting a stack 84*e8d8bef9SDimitry Andric // trace). Used to prevent deadlocks on platforms where libc unwinder calls 85*e8d8bef9SDimitry Andric // malloc internally. See PR17116 for more details. isUnwinding()86*e8d8bef9SDimitry Andric bool isUnwinding() const { return unwinding_; } setUnwinding(bool b)87*e8d8bef9SDimitry Andric void setUnwinding(bool b) { unwinding_ = b; } 88*e8d8bef9SDimitry Andric malloc_storage()89*e8d8bef9SDimitry Andric MemprofThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } stats()90*e8d8bef9SDimitry Andric MemprofStats &stats() { return stats_; } 91*e8d8bef9SDimitry Andric 92*e8d8bef9SDimitry Andric private: 93*e8d8bef9SDimitry Andric // NOTE: There is no MemprofThread constructor. It is allocated 94*e8d8bef9SDimitry Andric // via mmap() and *must* be valid in zero-initialized state. 95*e8d8bef9SDimitry Andric 96*e8d8bef9SDimitry Andric void SetThreadStackAndTls(const InitOptions *options); 97*e8d8bef9SDimitry Andric 98*e8d8bef9SDimitry Andric struct StackBounds { 99*e8d8bef9SDimitry Andric uptr bottom; 100*e8d8bef9SDimitry Andric uptr top; 101*e8d8bef9SDimitry Andric }; 102*e8d8bef9SDimitry Andric StackBounds GetStackBounds() const; 103*e8d8bef9SDimitry Andric 104*e8d8bef9SDimitry Andric MemprofThreadContext *context_; 105*e8d8bef9SDimitry Andric thread_callback_t start_routine_; 106*e8d8bef9SDimitry Andric void *arg_; 107*e8d8bef9SDimitry Andric 108*e8d8bef9SDimitry Andric uptr stack_top_; 109*e8d8bef9SDimitry Andric uptr stack_bottom_; 110*e8d8bef9SDimitry Andric 111*e8d8bef9SDimitry Andric uptr tls_begin_; 112*e8d8bef9SDimitry Andric uptr tls_end_; 113*e8d8bef9SDimitry Andric DTLS *dtls_; 114*e8d8bef9SDimitry Andric 115*e8d8bef9SDimitry Andric MemprofThreadLocalMallocStorage malloc_storage_; 116*e8d8bef9SDimitry Andric MemprofStats stats_; 117*e8d8bef9SDimitry Andric bool unwinding_; 118*e8d8bef9SDimitry Andric }; 119*e8d8bef9SDimitry Andric 120*e8d8bef9SDimitry Andric // Returns a single instance of registry. 121*e8d8bef9SDimitry Andric ThreadRegistry &memprofThreadRegistry(); 122*e8d8bef9SDimitry Andric 123*e8d8bef9SDimitry Andric // Must be called under ThreadRegistryLock. 124*e8d8bef9SDimitry Andric MemprofThreadContext *GetThreadContextByTidLocked(u32 tid); 125*e8d8bef9SDimitry Andric 126*e8d8bef9SDimitry Andric // Get the current thread. May return 0. 127*e8d8bef9SDimitry Andric MemprofThread *GetCurrentThread(); 128*e8d8bef9SDimitry Andric void SetCurrentThread(MemprofThread *t); 129*e8d8bef9SDimitry Andric u32 GetCurrentTidOrInvalid(); 130*e8d8bef9SDimitry Andric 131*e8d8bef9SDimitry Andric // Used to handle fork(). 132*e8d8bef9SDimitry Andric void EnsureMainThreadIDIsCorrect(); 133*e8d8bef9SDimitry Andric } // namespace __memprof 134*e8d8bef9SDimitry Andric 135*e8d8bef9SDimitry Andric #endif // MEMPROF_THREAD_H 136