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