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