1 #include "test/jemalloc_test.h"
2
TEST_BEGIN(test_stats_summary)3 TEST_BEGIN(test_stats_summary) {
4 size_t sz, allocated, active, resident, mapped;
5 int expected = config_stats ? 0 : ENOENT;
6
7 sz = sizeof(size_t);
8 assert_d_eq(mallctl("stats.allocated", (void *)&allocated, &sz, NULL,
9 0), expected, "Unexpected mallctl() result");
10 assert_d_eq(mallctl("stats.active", (void *)&active, &sz, NULL, 0),
11 expected, "Unexpected mallctl() result");
12 assert_d_eq(mallctl("stats.resident", (void *)&resident, &sz, NULL, 0),
13 expected, "Unexpected mallctl() result");
14 assert_d_eq(mallctl("stats.mapped", (void *)&mapped, &sz, NULL, 0),
15 expected, "Unexpected mallctl() result");
16
17 if (config_stats) {
18 assert_zu_le(allocated, active,
19 "allocated should be no larger than active");
20 assert_zu_lt(active, resident,
21 "active should be less than resident");
22 assert_zu_lt(active, mapped,
23 "active should be less than mapped");
24 }
25 }
26 TEST_END
27
TEST_BEGIN(test_stats_large)28 TEST_BEGIN(test_stats_large) {
29 void *p;
30 uint64_t epoch;
31 size_t allocated;
32 uint64_t nmalloc, ndalloc, nrequests;
33 size_t sz;
34 int expected = config_stats ? 0 : ENOENT;
35
36 p = mallocx(SMALL_MAXCLASS+1, MALLOCX_ARENA(0));
37 assert_ptr_not_null(p, "Unexpected mallocx() failure");
38
39 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
40 0, "Unexpected mallctl() failure");
41
42 sz = sizeof(size_t);
43 assert_d_eq(mallctl("stats.arenas.0.large.allocated",
44 (void *)&allocated, &sz, NULL, 0), expected,
45 "Unexpected mallctl() result");
46 sz = sizeof(uint64_t);
47 assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc,
48 &sz, NULL, 0), expected, "Unexpected mallctl() result");
49 assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc,
50 &sz, NULL, 0), expected, "Unexpected mallctl() result");
51 assert_d_eq(mallctl("stats.arenas.0.large.nrequests",
52 (void *)&nrequests, &sz, NULL, 0), expected,
53 "Unexpected mallctl() result");
54
55 if (config_stats) {
56 assert_zu_gt(allocated, 0,
57 "allocated should be greater than zero");
58 assert_u64_ge(nmalloc, ndalloc,
59 "nmalloc should be at least as large as ndalloc");
60 assert_u64_le(nmalloc, nrequests,
61 "nmalloc should no larger than nrequests");
62 }
63
64 dallocx(p, 0);
65 }
66 TEST_END
67
TEST_BEGIN(test_stats_arenas_summary)68 TEST_BEGIN(test_stats_arenas_summary) {
69 void *little, *large;
70 uint64_t epoch;
71 size_t sz;
72 int expected = config_stats ? 0 : ENOENT;
73 size_t mapped;
74 uint64_t dirty_npurge, dirty_nmadvise, dirty_purged;
75 uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged;
76
77 little = mallocx(SMALL_MAXCLASS, MALLOCX_ARENA(0));
78 assert_ptr_not_null(little, "Unexpected mallocx() failure");
79 large = mallocx((1U << LG_LARGE_MINCLASS), MALLOCX_ARENA(0));
80 assert_ptr_not_null(large, "Unexpected mallocx() failure");
81
82 dallocx(little, 0);
83 dallocx(large, 0);
84
85 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
86 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
87 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
88 "Unexpected mallctl() failure");
89
90 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
91 0, "Unexpected mallctl() failure");
92
93 sz = sizeof(size_t);
94 assert_d_eq(mallctl("stats.arenas.0.mapped", (void *)&mapped, &sz, NULL,
95 0), expected, "Unexepected mallctl() result");
96
97 sz = sizeof(uint64_t);
98 assert_d_eq(mallctl("stats.arenas.0.dirty_npurge",
99 (void *)&dirty_npurge, &sz, NULL, 0), expected,
100 "Unexepected mallctl() result");
101 assert_d_eq(mallctl("stats.arenas.0.dirty_nmadvise",
102 (void *)&dirty_nmadvise, &sz, NULL, 0), expected,
103 "Unexepected mallctl() result");
104 assert_d_eq(mallctl("stats.arenas.0.dirty_purged",
105 (void *)&dirty_purged, &sz, NULL, 0), expected,
106 "Unexepected mallctl() result");
107 assert_d_eq(mallctl("stats.arenas.0.muzzy_npurge",
108 (void *)&muzzy_npurge, &sz, NULL, 0), expected,
109 "Unexepected mallctl() result");
110 assert_d_eq(mallctl("stats.arenas.0.muzzy_nmadvise",
111 (void *)&muzzy_nmadvise, &sz, NULL, 0), expected,
112 "Unexepected mallctl() result");
113 assert_d_eq(mallctl("stats.arenas.0.muzzy_purged",
114 (void *)&muzzy_purged, &sz, NULL, 0), expected,
115 "Unexepected mallctl() result");
116
117 if (config_stats) {
118 if (!background_thread_enabled()) {
119 assert_u64_gt(dirty_npurge + muzzy_npurge, 0,
120 "At least one purge should have occurred");
121 }
122 assert_u64_le(dirty_nmadvise, dirty_purged,
123 "dirty_nmadvise should be no greater than dirty_purged");
124 assert_u64_le(muzzy_nmadvise, muzzy_purged,
125 "muzzy_nmadvise should be no greater than muzzy_purged");
126 }
127 }
128 TEST_END
129
130 void *
thd_start(void * arg)131 thd_start(void *arg) {
132 return NULL;
133 }
134
135 static void
no_lazy_lock(void)136 no_lazy_lock(void) {
137 thd_t thd;
138
139 thd_create(&thd, thd_start, NULL);
140 thd_join(thd, NULL);
141 }
142
TEST_BEGIN(test_stats_arenas_small)143 TEST_BEGIN(test_stats_arenas_small) {
144 void *p;
145 size_t sz, allocated;
146 uint64_t epoch, nmalloc, ndalloc, nrequests;
147 int expected = config_stats ? 0 : ENOENT;
148
149 no_lazy_lock(); /* Lazy locking would dodge tcache testing. */
150
151 p = mallocx(SMALL_MAXCLASS, MALLOCX_ARENA(0));
152 assert_ptr_not_null(p, "Unexpected mallocx() failure");
153
154 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
155 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
156
157 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
158 0, "Unexpected mallctl() failure");
159
160 sz = sizeof(size_t);
161 assert_d_eq(mallctl("stats.arenas.0.small.allocated",
162 (void *)&allocated, &sz, NULL, 0), expected,
163 "Unexpected mallctl() result");
164 sz = sizeof(uint64_t);
165 assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", (void *)&nmalloc,
166 &sz, NULL, 0), expected, "Unexpected mallctl() result");
167 assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", (void *)&ndalloc,
168 &sz, NULL, 0), expected, "Unexpected mallctl() result");
169 assert_d_eq(mallctl("stats.arenas.0.small.nrequests",
170 (void *)&nrequests, &sz, NULL, 0), expected,
171 "Unexpected mallctl() result");
172
173 if (config_stats) {
174 assert_zu_gt(allocated, 0,
175 "allocated should be greater than zero");
176 assert_u64_gt(nmalloc, 0,
177 "nmalloc should be no greater than zero");
178 assert_u64_ge(nmalloc, ndalloc,
179 "nmalloc should be at least as large as ndalloc");
180 assert_u64_gt(nrequests, 0,
181 "nrequests should be greater than zero");
182 }
183
184 dallocx(p, 0);
185 }
186 TEST_END
187
TEST_BEGIN(test_stats_arenas_large)188 TEST_BEGIN(test_stats_arenas_large) {
189 void *p;
190 size_t sz, allocated;
191 uint64_t epoch, nmalloc, ndalloc;
192 int expected = config_stats ? 0 : ENOENT;
193
194 p = mallocx((1U << LG_LARGE_MINCLASS), MALLOCX_ARENA(0));
195 assert_ptr_not_null(p, "Unexpected mallocx() failure");
196
197 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
198 0, "Unexpected mallctl() failure");
199
200 sz = sizeof(size_t);
201 assert_d_eq(mallctl("stats.arenas.0.large.allocated",
202 (void *)&allocated, &sz, NULL, 0), expected,
203 "Unexpected mallctl() result");
204 sz = sizeof(uint64_t);
205 assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc,
206 &sz, NULL, 0), expected, "Unexpected mallctl() result");
207 assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc,
208 &sz, NULL, 0), expected, "Unexpected mallctl() result");
209
210 if (config_stats) {
211 assert_zu_gt(allocated, 0,
212 "allocated should be greater than zero");
213 assert_u64_gt(nmalloc, 0,
214 "nmalloc should be greater than zero");
215 assert_u64_ge(nmalloc, ndalloc,
216 "nmalloc should be at least as large as ndalloc");
217 }
218
219 dallocx(p, 0);
220 }
221 TEST_END
222
223 static void
gen_mallctl_str(char * cmd,char * name,unsigned arena_ind)224 gen_mallctl_str(char *cmd, char *name, unsigned arena_ind) {
225 sprintf(cmd, "stats.arenas.%u.bins.0.%s", arena_ind, name);
226 }
227
TEST_BEGIN(test_stats_arenas_bins)228 TEST_BEGIN(test_stats_arenas_bins) {
229 test_skip_if(known_failure_on_android);
230 void *p;
231 size_t sz, curslabs, curregs;
232 uint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;
233 uint64_t nslabs, nreslabs;
234 int expected = config_stats ? 0 : ENOENT;
235
236 /* Make sure allocation below isn't satisfied by tcache. */
237 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
238 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
239
240 unsigned arena_ind, old_arena_ind;
241 sz = sizeof(unsigned);
242 assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0),
243 0, "Arena creation failure");
244 sz = sizeof(arena_ind);
245 assert_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz,
246 (void *)&arena_ind, sizeof(arena_ind)), 0,
247 "Unexpected mallctl() failure");
248
249 p = malloc(bin_infos[0].reg_size);
250 assert_ptr_not_null(p, "Unexpected malloc() failure");
251
252 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
253 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
254
255 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
256 0, "Unexpected mallctl() failure");
257
258 char cmd[128];
259 sz = sizeof(uint64_t);
260 gen_mallctl_str(cmd, "nmalloc", arena_ind);
261 assert_d_eq(mallctl(cmd, (void *)&nmalloc, &sz, NULL, 0), expected,
262 "Unexpected mallctl() result");
263 gen_mallctl_str(cmd, "ndalloc", arena_ind);
264 assert_d_eq(mallctl(cmd, (void *)&ndalloc, &sz, NULL, 0), expected,
265 "Unexpected mallctl() result");
266 gen_mallctl_str(cmd, "nrequests", arena_ind);
267 assert_d_eq(mallctl(cmd, (void *)&nrequests, &sz, NULL, 0), expected,
268 "Unexpected mallctl() result");
269 sz = sizeof(size_t);
270 gen_mallctl_str(cmd, "curregs", arena_ind);
271 assert_d_eq(mallctl(cmd, (void *)&curregs, &sz, NULL, 0), expected,
272 "Unexpected mallctl() result");
273
274 sz = sizeof(uint64_t);
275 gen_mallctl_str(cmd, "nfills", arena_ind);
276 assert_d_eq(mallctl(cmd, (void *)&nfills, &sz, NULL, 0), expected,
277 "Unexpected mallctl() result");
278 gen_mallctl_str(cmd, "nflushes", arena_ind);
279 assert_d_eq(mallctl(cmd, (void *)&nflushes, &sz, NULL, 0), expected,
280 "Unexpected mallctl() result");
281
282 gen_mallctl_str(cmd, "nslabs", arena_ind);
283 assert_d_eq(mallctl(cmd, (void *)&nslabs, &sz, NULL, 0), expected,
284 "Unexpected mallctl() result");
285 gen_mallctl_str(cmd, "nreslabs", arena_ind);
286 assert_d_eq(mallctl(cmd, (void *)&nreslabs, &sz, NULL, 0), expected,
287 "Unexpected mallctl() result");
288 sz = sizeof(size_t);
289 gen_mallctl_str(cmd, "curslabs", arena_ind);
290 assert_d_eq(mallctl(cmd, (void *)&curslabs, &sz, NULL, 0), expected,
291 "Unexpected mallctl() result");
292
293 if (config_stats) {
294 assert_u64_gt(nmalloc, 0,
295 "nmalloc should be greater than zero");
296 assert_u64_ge(nmalloc, ndalloc,
297 "nmalloc should be at least as large as ndalloc");
298 assert_u64_gt(nrequests, 0,
299 "nrequests should be greater than zero");
300 assert_zu_gt(curregs, 0,
301 "allocated should be greater than zero");
302 if (opt_tcache) {
303 assert_u64_gt(nfills, 0,
304 "At least one fill should have occurred");
305 assert_u64_gt(nflushes, 0,
306 "At least one flush should have occurred");
307 }
308 assert_u64_gt(nslabs, 0,
309 "At least one slab should have been allocated");
310 assert_zu_gt(curslabs, 0,
311 "At least one slab should be currently allocated");
312 }
313
314 dallocx(p, 0);
315 }
316 TEST_END
317
TEST_BEGIN(test_stats_arenas_lextents)318 TEST_BEGIN(test_stats_arenas_lextents) {
319 void *p;
320 uint64_t epoch, nmalloc, ndalloc;
321 size_t curlextents, sz, hsize;
322 int expected = config_stats ? 0 : ENOENT;
323
324 sz = sizeof(size_t);
325 assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&hsize, &sz, NULL,
326 0), 0, "Unexpected mallctl() failure");
327
328 p = mallocx(hsize, MALLOCX_ARENA(0));
329 assert_ptr_not_null(p, "Unexpected mallocx() failure");
330
331 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
332 0, "Unexpected mallctl() failure");
333
334 sz = sizeof(uint64_t);
335 assert_d_eq(mallctl("stats.arenas.0.lextents.0.nmalloc",
336 (void *)&nmalloc, &sz, NULL, 0), expected,
337 "Unexpected mallctl() result");
338 assert_d_eq(mallctl("stats.arenas.0.lextents.0.ndalloc",
339 (void *)&ndalloc, &sz, NULL, 0), expected,
340 "Unexpected mallctl() result");
341 sz = sizeof(size_t);
342 assert_d_eq(mallctl("stats.arenas.0.lextents.0.curlextents",
343 (void *)&curlextents, &sz, NULL, 0), expected,
344 "Unexpected mallctl() result");
345
346 if (config_stats) {
347 assert_u64_gt(nmalloc, 0,
348 "nmalloc should be greater than zero");
349 assert_u64_ge(nmalloc, ndalloc,
350 "nmalloc should be at least as large as ndalloc");
351 assert_u64_gt(curlextents, 0,
352 "At least one extent should be currently allocated");
353 }
354
355 dallocx(p, 0);
356 }
357 TEST_END
358
359 int
main(void)360 main(void) {
361 return test_no_reentrancy(
362 test_stats_summary,
363 test_stats_large,
364 test_stats_arenas_summary,
365 test_stats_arenas_small,
366 test_stats_arenas_large,
367 test_stats_arenas_bins,
368 test_stats_arenas_lextents);
369 }
370