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