1 #ifndef JEMALLOC_INTERNAL_PROF_STRUCTS_H 2 #define JEMALLOC_INTERNAL_PROF_STRUCTS_H 3 4 #include "jemalloc/internal/ckh.h" 5 #include "jemalloc/internal/edata.h" 6 #include "jemalloc/internal/mutex.h" 7 #include "jemalloc/internal/prng.h" 8 #include "jemalloc/internal/rb.h" 9 10 struct prof_bt_s { 11 /* Backtrace, stored as len program counters. */ 12 void **vec; 13 unsigned len; 14 }; 15 16 #ifdef JEMALLOC_PROF_LIBGCC 17 /* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */ 18 typedef struct { 19 void **vec; 20 unsigned *len; 21 unsigned max; 22 } prof_unwind_data_t; 23 #endif 24 25 struct prof_cnt_s { 26 /* Profiling counters. */ 27 uint64_t curobjs; 28 uint64_t curobjs_shifted_unbiased; 29 uint64_t curbytes; 30 uint64_t curbytes_unbiased; 31 uint64_t accumobjs; 32 uint64_t accumobjs_shifted_unbiased; 33 uint64_t accumbytes; 34 uint64_t accumbytes_unbiased; 35 }; 36 37 typedef enum { 38 prof_tctx_state_initializing, 39 prof_tctx_state_nominal, 40 prof_tctx_state_dumping, 41 prof_tctx_state_purgatory /* Dumper must finish destroying. */ 42 } prof_tctx_state_t; 43 44 struct prof_tctx_s { 45 /* Thread data for thread that performed the allocation. */ 46 prof_tdata_t *tdata; 47 48 /* 49 * Copy of tdata->thr_{uid,discrim}, necessary because tdata may be 50 * defunct during teardown. 51 */ 52 uint64_t thr_uid; 53 uint64_t thr_discrim; 54 55 /* 56 * Reference count of how many times this tctx object is referenced in 57 * recent allocation / deallocation records, protected by tdata->lock. 58 */ 59 uint64_t recent_count; 60 61 /* Profiling counters, protected by tdata->lock. */ 62 prof_cnt_t cnts; 63 64 /* Associated global context. */ 65 prof_gctx_t *gctx; 66 67 /* 68 * UID that distinguishes multiple tctx's created by the same thread, 69 * but coexisting in gctx->tctxs. There are two ways that such 70 * coexistence can occur: 71 * - A dumper thread can cause a tctx to be retained in the purgatory 72 * state. 73 * - Although a single "producer" thread must create all tctx's which 74 * share the same thr_uid, multiple "consumers" can each concurrently 75 * execute portions of prof_tctx_destroy(). prof_tctx_destroy() only 76 * gets called once each time cnts.cur{objs,bytes} drop to 0, but this 77 * threshold can be hit again before the first consumer finishes 78 * executing prof_tctx_destroy(). 79 */ 80 uint64_t tctx_uid; 81 82 /* Linkage into gctx's tctxs. */ 83 rb_node(prof_tctx_t) tctx_link; 84 85 /* 86 * True during prof_alloc_prep()..prof_malloc_sample_object(), prevents 87 * sample vs destroy race. 88 */ 89 bool prepared; 90 91 /* Current dump-related state, protected by gctx->lock. */ 92 prof_tctx_state_t state; 93 94 /* 95 * Copy of cnts snapshotted during early dump phase, protected by 96 * dump_mtx. 97 */ 98 prof_cnt_t dump_cnts; 99 }; 100 typedef rb_tree(prof_tctx_t) prof_tctx_tree_t; 101 102 struct prof_info_s { 103 /* Time when the allocation was made. */ 104 nstime_t alloc_time; 105 /* Points to the prof_tctx_t corresponding to the allocation. */ 106 prof_tctx_t *alloc_tctx; 107 /* Allocation request size. */ 108 size_t alloc_size; 109 }; 110 111 struct prof_gctx_s { 112 /* Protects nlimbo, cnt_summed, and tctxs. */ 113 malloc_mutex_t *lock; 114 115 /* 116 * Number of threads that currently cause this gctx to be in a state of 117 * limbo due to one of: 118 * - Initializing this gctx. 119 * - Initializing per thread counters associated with this gctx. 120 * - Preparing to destroy this gctx. 121 * - Dumping a heap profile that includes this gctx. 122 * nlimbo must be 1 (single destroyer) in order to safely destroy the 123 * gctx. 124 */ 125 unsigned nlimbo; 126 127 /* 128 * Tree of profile counters, one for each thread that has allocated in 129 * this context. 130 */ 131 prof_tctx_tree_t tctxs; 132 133 /* Linkage for tree of contexts to be dumped. */ 134 rb_node(prof_gctx_t) dump_link; 135 136 /* Temporary storage for summation during dump. */ 137 prof_cnt_t cnt_summed; 138 139 /* Associated backtrace. */ 140 prof_bt_t bt; 141 142 /* Backtrace vector, variable size, referred to by bt. */ 143 void *vec[1]; 144 }; 145 typedef rb_tree(prof_gctx_t) prof_gctx_tree_t; 146 147 struct prof_tdata_s { 148 malloc_mutex_t *lock; 149 150 /* Monotonically increasing unique thread identifier. */ 151 uint64_t thr_uid; 152 153 /* 154 * Monotonically increasing discriminator among tdata structures 155 * associated with the same thr_uid. 156 */ 157 uint64_t thr_discrim; 158 159 /* Included in heap profile dumps if non-NULL. */ 160 char *thread_name; 161 162 bool attached; 163 bool expired; 164 165 rb_node(prof_tdata_t) tdata_link; 166 167 /* 168 * Counter used to initialize prof_tctx_t's tctx_uid. No locking is 169 * necessary when incrementing this field, because only one thread ever 170 * does so. 171 */ 172 uint64_t tctx_uid_next; 173 174 /* 175 * Hash of (prof_bt_t *)-->(prof_tctx_t *). Each thread tracks 176 * backtraces for which it has non-zero allocation/deallocation counters 177 * associated with thread-specific prof_tctx_t objects. Other threads 178 * may write to prof_tctx_t contents when freeing associated objects. 179 */ 180 ckh_t bt2tctx; 181 182 /* State used to avoid dumping while operating on prof internals. */ 183 bool enq; 184 bool enq_idump; 185 bool enq_gdump; 186 187 /* 188 * Set to true during an early dump phase for tdata's which are 189 * currently being dumped. New threads' tdata's have this initialized 190 * to false so that they aren't accidentally included in later dump 191 * phases. 192 */ 193 bool dumping; 194 195 /* 196 * True if profiling is active for this tdata's thread 197 * (thread.prof.active mallctl). 198 */ 199 bool active; 200 201 /* Temporary storage for summation during dump. */ 202 prof_cnt_t cnt_summed; 203 204 /* Backtrace vector, used for calls to prof_backtrace(). */ 205 void *vec[PROF_BT_MAX]; 206 }; 207 typedef rb_tree(prof_tdata_t) prof_tdata_tree_t; 208 209 struct prof_recent_s { 210 nstime_t alloc_time; 211 nstime_t dalloc_time; 212 213 ql_elm(prof_recent_t) link; 214 size_t size; 215 size_t usize; 216 atomic_p_t alloc_edata; /* NULL means allocation has been freed. */ 217 prof_tctx_t *alloc_tctx; 218 prof_tctx_t *dalloc_tctx; 219 }; 220 221 #endif /* JEMALLOC_INTERNAL_PROF_STRUCTS_H */ 222