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
10struct 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. */
18typedef struct {
19 void **vec;
20 unsigned *len;
21 unsigned max;
22} prof_unwind_data_t;
23#endif
24
25struct 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
37typedef 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
44struct 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};
100typedef rb_tree(prof_tctx_t) prof_tctx_tree_t;
101
102struct 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
111struct 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};
145typedef rb_tree(prof_gctx_t) prof_gctx_tree_t;
146
147struct 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};
207typedef rb_tree(prof_tdata_t) prof_tdata_tree_t;
208
209struct 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