xref: /openbsd-src/gnu/llvm/compiler-rt/lib/memprof/memprof_thread.h (revision d89ec533011f513df1010f142a111086a0785f09)
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