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