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