xref: /netbsd-src/external/bsd/jemalloc.old/include/jemalloc/internal/prof_structs.h (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
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