1 #include "test/jemalloc_test.h"
2 
TEST_BEGIN(test_stats_summary)3 TEST_BEGIN(test_stats_summary)
4 {
5 	size_t *cactive;
6 	size_t sz, allocated, active, resident, mapped;
7 	int expected = config_stats ? 0 : ENOENT;
8 
9 	sz = sizeof(cactive);
10 	assert_d_eq(mallctl("stats.cactive", &cactive, &sz, NULL, 0), expected,
11 	    "Unexpected mallctl() result");
12 
13 	sz = sizeof(size_t);
14 	assert_d_eq(mallctl("stats.allocated", &allocated, &sz, NULL, 0),
15 	    expected, "Unexpected mallctl() result");
16 	assert_d_eq(mallctl("stats.active", &active, &sz, NULL, 0), expected,
17 	    "Unexpected mallctl() result");
18 	assert_d_eq(mallctl("stats.resident", &resident, &sz, NULL, 0),
19 	    expected, "Unexpected mallctl() result");
20 	assert_d_eq(mallctl("stats.mapped", &mapped, &sz, NULL, 0), expected,
21 	    "Unexpected mallctl() result");
22 
23 	if (config_stats) {
24 		assert_zu_le(active, *cactive,
25 		    "active should be no larger than cactive");
26 		assert_zu_le(allocated, active,
27 		    "allocated should be no larger than active");
28 		assert_zu_lt(active, resident,
29 		    "active should be less than resident");
30 		assert_zu_lt(active, mapped,
31 		    "active should be less than mapped");
32 	}
33 }
34 TEST_END
35 
TEST_BEGIN(test_stats_huge)36 TEST_BEGIN(test_stats_huge)
37 {
38 	void *p;
39 	uint64_t epoch;
40 	size_t allocated;
41 	uint64_t nmalloc, ndalloc, nrequests;
42 	size_t sz;
43 	int expected = config_stats ? 0 : ENOENT;
44 
45 	p = mallocx(large_maxclass+1, 0);
46 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
47 
48 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
49 	    "Unexpected mallctl() failure");
50 
51 	sz = sizeof(size_t);
52 	assert_d_eq(mallctl("stats.arenas.0.huge.allocated", &allocated, &sz,
53 	    NULL, 0), expected, "Unexpected mallctl() result");
54 	sz = sizeof(uint64_t);
55 	assert_d_eq(mallctl("stats.arenas.0.huge.nmalloc", &nmalloc, &sz, NULL,
56 	    0), expected, "Unexpected mallctl() result");
57 	assert_d_eq(mallctl("stats.arenas.0.huge.ndalloc", &ndalloc, &sz, NULL,
58 	    0), expected, "Unexpected mallctl() result");
59 	assert_d_eq(mallctl("stats.arenas.0.huge.nrequests", &nrequests, &sz,
60 	    NULL, 0), expected, "Unexpected mallctl() result");
61 
62 	if (config_stats) {
63 		assert_zu_gt(allocated, 0,
64 		    "allocated should be greater than zero");
65 		assert_u64_ge(nmalloc, ndalloc,
66 		    "nmalloc should be at least as large as ndalloc");
67 		assert_u64_le(nmalloc, nrequests,
68 		    "nmalloc should no larger than nrequests");
69 	}
70 
71 	dallocx(p, 0);
72 }
73 TEST_END
74 
TEST_BEGIN(test_stats_arenas_summary)75 TEST_BEGIN(test_stats_arenas_summary)
76 {
77 	unsigned arena;
78 	void *little, *large, *huge;
79 	uint64_t epoch;
80 	size_t sz;
81 	int expected = config_stats ? 0 : ENOENT;
82 	size_t mapped;
83 	uint64_t npurge, nmadvise, purged;
84 
85 	arena = 0;
86 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
87 	    0, "Unexpected mallctl() failure");
88 
89 	little = mallocx(SMALL_MAXCLASS, 0);
90 	assert_ptr_not_null(little, "Unexpected mallocx() failure");
91 	large = mallocx(large_maxclass, 0);
92 	assert_ptr_not_null(large, "Unexpected mallocx() failure");
93 	huge = mallocx(chunksize, 0);
94 	assert_ptr_not_null(huge, "Unexpected mallocx() failure");
95 
96 	dallocx(little, 0);
97 	dallocx(large, 0);
98 	dallocx(huge, 0);
99 
100 	assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
101 	    "Unexpected mallctl() failure");
102 
103 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
104 	    "Unexpected mallctl() failure");
105 
106 	sz = sizeof(size_t);
107 	assert_d_eq(mallctl("stats.arenas.0.mapped", &mapped, &sz, NULL, 0),
108 	    expected, "Unexepected mallctl() result");
109 	sz = sizeof(uint64_t);
110 	assert_d_eq(mallctl("stats.arenas.0.npurge", &npurge, &sz, NULL, 0),
111 	    expected, "Unexepected mallctl() result");
112 	assert_d_eq(mallctl("stats.arenas.0.nmadvise", &nmadvise, &sz, NULL, 0),
113 	    expected, "Unexepected mallctl() result");
114 	assert_d_eq(mallctl("stats.arenas.0.purged", &purged, &sz, NULL, 0),
115 	    expected, "Unexepected mallctl() result");
116 
117 	if (config_stats) {
118 		assert_u64_gt(npurge, 0,
119 		    "At least one purge should have occurred");
120 		assert_u64_le(nmadvise, purged,
121 		    "nmadvise should be no greater than purged");
122 	}
123 }
124 TEST_END
125 
126 void *
thd_start(void * arg)127 thd_start(void *arg)
128 {
129 
130 	return (NULL);
131 }
132 
133 static void
no_lazy_lock(void)134 no_lazy_lock(void)
135 {
136 	thd_t thd;
137 
138 	thd_create(&thd, thd_start, NULL);
139 	thd_join(thd, NULL);
140 }
141 
TEST_BEGIN(test_stats_arenas_small)142 TEST_BEGIN(test_stats_arenas_small)
143 {
144 	unsigned arena;
145 	void *p;
146 	size_t sz, allocated;
147 	uint64_t epoch, nmalloc, ndalloc, nrequests;
148 	int expected = config_stats ? 0 : ENOENT;
149 
150 	no_lazy_lock(); /* Lazy locking would dodge tcache testing. */
151 
152 	arena = 0;
153 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
154 	    0, "Unexpected mallctl() failure");
155 
156 	p = mallocx(SMALL_MAXCLASS, 0);
157 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
158 
159 	assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
160 	    config_tcache ? 0 : ENOENT, "Unexpected mallctl() result");
161 
162 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
163 	    "Unexpected mallctl() failure");
164 
165 	sz = sizeof(size_t);
166 	assert_d_eq(mallctl("stats.arenas.0.small.allocated", &allocated, &sz,
167 	    NULL, 0), expected, "Unexpected mallctl() result");
168 	sz = sizeof(uint64_t);
169 	assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", &nmalloc, &sz,
170 	    NULL, 0), expected, "Unexpected mallctl() result");
171 	assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", &ndalloc, &sz,
172 	    NULL, 0), expected, "Unexpected mallctl() result");
173 	assert_d_eq(mallctl("stats.arenas.0.small.nrequests", &nrequests, &sz,
174 	    NULL, 0), expected, "Unexpected mallctl() result");
175 
176 	if (config_stats) {
177 		assert_zu_gt(allocated, 0,
178 		    "allocated should be greater than zero");
179 		assert_u64_gt(nmalloc, 0,
180 		    "nmalloc should be no greater than zero");
181 		assert_u64_ge(nmalloc, ndalloc,
182 		    "nmalloc should be at least as large as ndalloc");
183 		assert_u64_gt(nrequests, 0,
184 		    "nrequests should be greater than zero");
185 	}
186 
187 	dallocx(p, 0);
188 }
189 TEST_END
190 
TEST_BEGIN(test_stats_arenas_large)191 TEST_BEGIN(test_stats_arenas_large)
192 {
193 	unsigned arena;
194 	void *p;
195 	size_t sz, allocated;
196 	uint64_t epoch, nmalloc, ndalloc, nrequests;
197 	int expected = config_stats ? 0 : ENOENT;
198 
199 	arena = 0;
200 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
201 	    0, "Unexpected mallctl() failure");
202 
203 	p = mallocx(large_maxclass, 0);
204 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
205 
206 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
207 	    "Unexpected mallctl() failure");
208 
209 	sz = sizeof(size_t);
210 	assert_d_eq(mallctl("stats.arenas.0.large.allocated", &allocated, &sz,
211 	    NULL, 0), expected, "Unexpected mallctl() result");
212 	sz = sizeof(uint64_t);
213 	assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", &nmalloc, &sz,
214 	    NULL, 0), expected, "Unexpected mallctl() result");
215 	assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", &ndalloc, &sz,
216 	    NULL, 0), expected, "Unexpected mallctl() result");
217 	assert_d_eq(mallctl("stats.arenas.0.large.nrequests", &nrequests, &sz,
218 	    NULL, 0), expected, "Unexpected mallctl() result");
219 
220 	if (config_stats) {
221 		assert_zu_gt(allocated, 0,
222 		    "allocated should be greater than zero");
223 		assert_zu_gt(nmalloc, 0,
224 		    "nmalloc should be greater than zero");
225 		assert_zu_ge(nmalloc, ndalloc,
226 		    "nmalloc should be at least as large as ndalloc");
227 		assert_zu_gt(nrequests, 0,
228 		    "nrequests should be greater than zero");
229 	}
230 
231 	dallocx(p, 0);
232 }
233 TEST_END
234 
TEST_BEGIN(test_stats_arenas_huge)235 TEST_BEGIN(test_stats_arenas_huge)
236 {
237 	unsigned arena;
238 	void *p;
239 	size_t sz, allocated;
240 	uint64_t epoch, nmalloc, ndalloc;
241 	int expected = config_stats ? 0 : ENOENT;
242 
243 	arena = 0;
244 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
245 	    0, "Unexpected mallctl() failure");
246 
247 	p = mallocx(chunksize, 0);
248 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
249 
250 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
251 	    "Unexpected mallctl() failure");
252 
253 	sz = sizeof(size_t);
254 	assert_d_eq(mallctl("stats.arenas.0.huge.allocated", &allocated, &sz,
255 	    NULL, 0), expected, "Unexpected mallctl() result");
256 	sz = sizeof(uint64_t);
257 	assert_d_eq(mallctl("stats.arenas.0.huge.nmalloc", &nmalloc, &sz,
258 	    NULL, 0), expected, "Unexpected mallctl() result");
259 	assert_d_eq(mallctl("stats.arenas.0.huge.ndalloc", &ndalloc, &sz,
260 	    NULL, 0), expected, "Unexpected mallctl() result");
261 
262 	if (config_stats) {
263 		assert_zu_gt(allocated, 0,
264 		    "allocated should be greater than zero");
265 		assert_zu_gt(nmalloc, 0,
266 		    "nmalloc should be greater than zero");
267 		assert_zu_ge(nmalloc, ndalloc,
268 		    "nmalloc should be at least as large as ndalloc");
269 	}
270 
271 	dallocx(p, 0);
272 }
273 TEST_END
274 
TEST_BEGIN(test_stats_arenas_bins)275 TEST_BEGIN(test_stats_arenas_bins)
276 {
277 	unsigned arena;
278 	void *p;
279 	size_t sz, curruns, curregs;
280 	uint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;
281 	uint64_t nruns, nreruns;
282 	int expected = config_stats ? 0 : ENOENT;
283 
284 	arena = 0;
285 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
286 	    0, "Unexpected mallctl() failure");
287 
288 	p = mallocx(arena_bin_info[0].reg_size, 0);
289 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
290 
291 	assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
292 	    config_tcache ? 0 : ENOENT, "Unexpected mallctl() result");
293 
294 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
295 	    "Unexpected mallctl() failure");
296 
297 	sz = sizeof(uint64_t);
298 	assert_d_eq(mallctl("stats.arenas.0.bins.0.nmalloc", &nmalloc, &sz,
299 	    NULL, 0), expected, "Unexpected mallctl() result");
300 	assert_d_eq(mallctl("stats.arenas.0.bins.0.ndalloc", &ndalloc, &sz,
301 	    NULL, 0), expected, "Unexpected mallctl() result");
302 	assert_d_eq(mallctl("stats.arenas.0.bins.0.nrequests", &nrequests, &sz,
303 	    NULL, 0), expected, "Unexpected mallctl() result");
304 	sz = sizeof(size_t);
305 	assert_d_eq(mallctl("stats.arenas.0.bins.0.curregs", &curregs, &sz,
306 	    NULL, 0), expected, "Unexpected mallctl() result");
307 
308 	sz = sizeof(uint64_t);
309 	assert_d_eq(mallctl("stats.arenas.0.bins.0.nfills", &nfills, &sz,
310 	    NULL, 0), config_tcache ? expected : ENOENT,
311 	    "Unexpected mallctl() result");
312 	assert_d_eq(mallctl("stats.arenas.0.bins.0.nflushes", &nflushes, &sz,
313 	    NULL, 0), config_tcache ? expected : ENOENT,
314 	    "Unexpected mallctl() result");
315 
316 	assert_d_eq(mallctl("stats.arenas.0.bins.0.nruns", &nruns, &sz,
317 	    NULL, 0), expected, "Unexpected mallctl() result");
318 	assert_d_eq(mallctl("stats.arenas.0.bins.0.nreruns", &nreruns, &sz,
319 	    NULL, 0), expected, "Unexpected mallctl() result");
320 	sz = sizeof(size_t);
321 	assert_d_eq(mallctl("stats.arenas.0.bins.0.curruns", &curruns, &sz,
322 	    NULL, 0), expected, "Unexpected mallctl() result");
323 
324 	if (config_stats) {
325 		assert_u64_gt(nmalloc, 0,
326 		    "nmalloc should be greater than zero");
327 		assert_u64_ge(nmalloc, ndalloc,
328 		    "nmalloc should be at least as large as ndalloc");
329 		assert_u64_gt(nrequests, 0,
330 		    "nrequests should be greater than zero");
331 		assert_zu_gt(curregs, 0,
332 		    "allocated should be greater than zero");
333 		if (config_tcache) {
334 			assert_u64_gt(nfills, 0,
335 			    "At least one fill should have occurred");
336 			assert_u64_gt(nflushes, 0,
337 			    "At least one flush should have occurred");
338 		}
339 		assert_u64_gt(nruns, 0,
340 		    "At least one run should have been allocated");
341 		assert_zu_gt(curruns, 0,
342 		    "At least one run should be currently allocated");
343 	}
344 
345 	dallocx(p, 0);
346 }
347 TEST_END
348 
TEST_BEGIN(test_stats_arenas_lruns)349 TEST_BEGIN(test_stats_arenas_lruns)
350 {
351 	unsigned arena;
352 	void *p;
353 	uint64_t epoch, nmalloc, ndalloc, nrequests;
354 	size_t curruns, sz;
355 	int expected = config_stats ? 0 : ENOENT;
356 
357 	arena = 0;
358 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
359 	    0, "Unexpected mallctl() failure");
360 
361 	p = mallocx(LARGE_MINCLASS, 0);
362 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
363 
364 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
365 	    "Unexpected mallctl() failure");
366 
367 	sz = sizeof(uint64_t);
368 	assert_d_eq(mallctl("stats.arenas.0.lruns.0.nmalloc", &nmalloc, &sz,
369 	    NULL, 0), expected, "Unexpected mallctl() result");
370 	assert_d_eq(mallctl("stats.arenas.0.lruns.0.ndalloc", &ndalloc, &sz,
371 	    NULL, 0), expected, "Unexpected mallctl() result");
372 	assert_d_eq(mallctl("stats.arenas.0.lruns.0.nrequests", &nrequests, &sz,
373 	    NULL, 0), expected, "Unexpected mallctl() result");
374 	sz = sizeof(size_t);
375 	assert_d_eq(mallctl("stats.arenas.0.lruns.0.curruns", &curruns, &sz,
376 	    NULL, 0), expected, "Unexpected mallctl() result");
377 
378 	if (config_stats) {
379 		assert_u64_gt(nmalloc, 0,
380 		    "nmalloc should be greater than zero");
381 		assert_u64_ge(nmalloc, ndalloc,
382 		    "nmalloc should be at least as large as ndalloc");
383 		assert_u64_gt(nrequests, 0,
384 		    "nrequests should be greater than zero");
385 		assert_u64_gt(curruns, 0,
386 		    "At least one run should be currently allocated");
387 	}
388 
389 	dallocx(p, 0);
390 }
391 TEST_END
392 
TEST_BEGIN(test_stats_arenas_hchunks)393 TEST_BEGIN(test_stats_arenas_hchunks)
394 {
395 	unsigned arena;
396 	void *p;
397 	uint64_t epoch, nmalloc, ndalloc;
398 	size_t curhchunks, sz;
399 	int expected = config_stats ? 0 : ENOENT;
400 
401 	arena = 0;
402 	assert_d_eq(mallctl("thread.arena", NULL, NULL, &arena, sizeof(arena)),
403 	    0, "Unexpected mallctl() failure");
404 
405 	p = mallocx(chunksize, 0);
406 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
407 
408 	assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)), 0,
409 	    "Unexpected mallctl() failure");
410 
411 	sz = sizeof(uint64_t);
412 	assert_d_eq(mallctl("stats.arenas.0.hchunks.0.nmalloc", &nmalloc, &sz,
413 	    NULL, 0), expected, "Unexpected mallctl() result");
414 	assert_d_eq(mallctl("stats.arenas.0.hchunks.0.ndalloc", &ndalloc, &sz,
415 	    NULL, 0), expected, "Unexpected mallctl() result");
416 	sz = sizeof(size_t);
417 	assert_d_eq(mallctl("stats.arenas.0.hchunks.0.curhchunks", &curhchunks,
418 	    &sz, NULL, 0), expected, "Unexpected mallctl() result");
419 
420 	if (config_stats) {
421 		assert_u64_gt(nmalloc, 0,
422 		    "nmalloc should be greater than zero");
423 		assert_u64_ge(nmalloc, ndalloc,
424 		    "nmalloc should be at least as large as ndalloc");
425 		assert_u64_gt(curhchunks, 0,
426 		    "At least one chunk should be currently allocated");
427 	}
428 
429 	dallocx(p, 0);
430 }
431 TEST_END
432 
433 int
main(void)434 main(void)
435 {
436 
437 	return (test(
438 	    test_stats_summary,
439 	    test_stats_huge,
440 	    test_stats_arenas_summary,
441 	    test_stats_arenas_small,
442 	    test_stats_arenas_large,
443 	    test_stats_arenas_huge,
444 	    test_stats_arenas_bins,
445 	    test_stats_arenas_lruns,
446 	    test_stats_arenas_hchunks));
447 }
448