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