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(SC_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(SC_SMALL_MAXCLASS, MALLOCX_ARENA(0));
78 	assert_ptr_not_null(little, "Unexpected mallocx() failure");
79 	large = mallocx((1U << SC_LG_LARGE_MINCLASS),
80 	    MALLOCX_ARENA(0));
81 	assert_ptr_not_null(large, "Unexpected mallocx() failure");
82 
83 	dallocx(little, 0);
84 	dallocx(large, 0);
85 
86 	assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
87 	    opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
88 	assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
89 	    "Unexpected mallctl() failure");
90 
91 	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
92 	    0, "Unexpected mallctl() failure");
93 
94 	sz = sizeof(size_t);
95 	assert_d_eq(mallctl("stats.arenas.0.mapped", (void *)&mapped, &sz, NULL,
96 	    0), expected, "Unexepected mallctl() result");
97 
98 	sz = sizeof(uint64_t);
99 	assert_d_eq(mallctl("stats.arenas.0.dirty_npurge",
100 	    (void *)&dirty_npurge, &sz, NULL, 0), expected,
101 	    "Unexepected mallctl() result");
102 	assert_d_eq(mallctl("stats.arenas.0.dirty_nmadvise",
103 	    (void *)&dirty_nmadvise, &sz, NULL, 0), expected,
104 	    "Unexepected mallctl() result");
105 	assert_d_eq(mallctl("stats.arenas.0.dirty_purged",
106 	    (void *)&dirty_purged, &sz, NULL, 0), expected,
107 	    "Unexepected mallctl() result");
108 	assert_d_eq(mallctl("stats.arenas.0.muzzy_npurge",
109 	    (void *)&muzzy_npurge, &sz, NULL, 0), expected,
110 	    "Unexepected mallctl() result");
111 	assert_d_eq(mallctl("stats.arenas.0.muzzy_nmadvise",
112 	    (void *)&muzzy_nmadvise, &sz, NULL, 0), expected,
113 	    "Unexepected mallctl() result");
114 	assert_d_eq(mallctl("stats.arenas.0.muzzy_purged",
115 	    (void *)&muzzy_purged, &sz, NULL, 0), expected,
116 	    "Unexepected mallctl() result");
117 
118 	if (config_stats) {
119 		if (!background_thread_enabled()) {
120 			assert_u64_gt(dirty_npurge + muzzy_npurge, 0,
121 			    "At least one purge should have occurred");
122 		}
123 		assert_u64_le(dirty_nmadvise, dirty_purged,
124 		    "dirty_nmadvise should be no greater than dirty_purged");
125 		assert_u64_le(muzzy_nmadvise, muzzy_purged,
126 		    "muzzy_nmadvise should be no greater than muzzy_purged");
127 	}
128 }
129 TEST_END
130 
131 void *
thd_start(void * arg)132 thd_start(void *arg) {
133 	return NULL;
134 }
135 
136 static void
no_lazy_lock(void)137 no_lazy_lock(void) {
138 	thd_t thd;
139 
140 	thd_create(&thd, thd_start, NULL);
141 	thd_join(thd, NULL);
142 }
143 
TEST_BEGIN(test_stats_arenas_small)144 TEST_BEGIN(test_stats_arenas_small) {
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 	p = mallocx(SC_SMALL_MAXCLASS, MALLOCX_ARENA(0));
153 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
154 
155 	assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
156 	    opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
157 
158 	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
159 	    0, "Unexpected mallctl() failure");
160 
161 	sz = sizeof(size_t);
162 	assert_d_eq(mallctl("stats.arenas.0.small.allocated",
163 	    (void *)&allocated, &sz, NULL, 0), expected,
164 	    "Unexpected mallctl() result");
165 	sz = sizeof(uint64_t);
166 	assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", (void *)&nmalloc,
167 	    &sz, NULL, 0), expected, "Unexpected mallctl() result");
168 	assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", (void *)&ndalloc,
169 	    &sz, NULL, 0), expected, "Unexpected mallctl() result");
170 	assert_d_eq(mallctl("stats.arenas.0.small.nrequests",
171 	    (void *)&nrequests, &sz, NULL, 0), expected,
172 	    "Unexpected mallctl() result");
173 
174 	if (config_stats) {
175 		assert_zu_gt(allocated, 0,
176 		    "allocated should be greater than zero");
177 		assert_u64_gt(nmalloc, 0,
178 		    "nmalloc should be no greater than zero");
179 		assert_u64_ge(nmalloc, ndalloc,
180 		    "nmalloc should be at least as large as ndalloc");
181 		assert_u64_gt(nrequests, 0,
182 		    "nrequests should be greater than zero");
183 	}
184 
185 	dallocx(p, 0);
186 }
187 TEST_END
188 
TEST_BEGIN(test_stats_arenas_large)189 TEST_BEGIN(test_stats_arenas_large) {
190 	void *p;
191 	size_t sz, allocated;
192 	uint64_t epoch, nmalloc, ndalloc;
193 	int expected = config_stats ? 0 : ENOENT;
194 
195 	p = mallocx((1U << SC_LG_LARGE_MINCLASS), MALLOCX_ARENA(0));
196 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
197 
198 	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
199 	    0, "Unexpected mallctl() failure");
200 
201 	sz = sizeof(size_t);
202 	assert_d_eq(mallctl("stats.arenas.0.large.allocated",
203 	    (void *)&allocated, &sz, NULL, 0), expected,
204 	    "Unexpected mallctl() result");
205 	sz = sizeof(uint64_t);
206 	assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc,
207 	    &sz, NULL, 0), expected, "Unexpected mallctl() result");
208 	assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc,
209 	    &sz, NULL, 0), expected, "Unexpected mallctl() result");
210 
211 	if (config_stats) {
212 		assert_zu_gt(allocated, 0,
213 		    "allocated should be greater than zero");
214 		assert_u64_gt(nmalloc, 0,
215 		    "nmalloc should be greater than zero");
216 		assert_u64_ge(nmalloc, ndalloc,
217 		    "nmalloc should be at least as large as ndalloc");
218 	}
219 
220 	dallocx(p, 0);
221 }
222 TEST_END
223 
224 static void
gen_mallctl_str(char * cmd,char * name,unsigned arena_ind)225 gen_mallctl_str(char *cmd, char *name, unsigned arena_ind) {
226 	sprintf(cmd, "stats.arenas.%u.bins.0.%s", arena_ind, name);
227 }
228 
TEST_BEGIN(test_stats_arenas_bins)229 TEST_BEGIN(test_stats_arenas_bins) {
230 	void *p;
231 	size_t sz, curslabs, curregs, nonfull_slabs;
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 	gen_mallctl_str(cmd, "nonfull_slabs", arena_ind);
293 	assert_d_eq(mallctl(cmd, (void *)&nonfull_slabs, &sz, NULL, 0),
294 	    expected, "Unexpected mallctl() result");
295 
296 	if (config_stats) {
297 		assert_u64_gt(nmalloc, 0,
298 		    "nmalloc should be greater than zero");
299 		assert_u64_ge(nmalloc, ndalloc,
300 		    "nmalloc should be at least as large as ndalloc");
301 		assert_u64_gt(nrequests, 0,
302 		    "nrequests should be greater than zero");
303 		assert_zu_gt(curregs, 0,
304 		    "allocated should be greater than zero");
305 		if (opt_tcache) {
306 			assert_u64_gt(nfills, 0,
307 			    "At least one fill should have occurred");
308 			assert_u64_gt(nflushes, 0,
309 			    "At least one flush should have occurred");
310 		}
311 		assert_u64_gt(nslabs, 0,
312 		    "At least one slab should have been allocated");
313 		assert_zu_gt(curslabs, 0,
314 		    "At least one slab should be currently allocated");
315 		assert_zu_eq(nonfull_slabs, 0,
316 		    "slabs_nonfull should be empty");
317 	}
318 
319 	dallocx(p, 0);
320 }
321 TEST_END
322 
TEST_BEGIN(test_stats_arenas_lextents)323 TEST_BEGIN(test_stats_arenas_lextents) {
324 	void *p;
325 	uint64_t epoch, nmalloc, ndalloc;
326 	size_t curlextents, sz, hsize;
327 	int expected = config_stats ? 0 : ENOENT;
328 
329 	sz = sizeof(size_t);
330 	assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&hsize, &sz, NULL,
331 	    0), 0, "Unexpected mallctl() failure");
332 
333 	p = mallocx(hsize, MALLOCX_ARENA(0));
334 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
335 
336 	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
337 	    0, "Unexpected mallctl() failure");
338 
339 	sz = sizeof(uint64_t);
340 	assert_d_eq(mallctl("stats.arenas.0.lextents.0.nmalloc",
341 	    (void *)&nmalloc, &sz, NULL, 0), expected,
342 	    "Unexpected mallctl() result");
343 	assert_d_eq(mallctl("stats.arenas.0.lextents.0.ndalloc",
344 	    (void *)&ndalloc, &sz, NULL, 0), expected,
345 	    "Unexpected mallctl() result");
346 	sz = sizeof(size_t);
347 	assert_d_eq(mallctl("stats.arenas.0.lextents.0.curlextents",
348 	    (void *)&curlextents, &sz, NULL, 0), expected,
349 	    "Unexpected mallctl() result");
350 
351 	if (config_stats) {
352 		assert_u64_gt(nmalloc, 0,
353 		    "nmalloc should be greater than zero");
354 		assert_u64_ge(nmalloc, ndalloc,
355 		    "nmalloc should be at least as large as ndalloc");
356 		assert_u64_gt(curlextents, 0,
357 		    "At least one extent should be currently allocated");
358 	}
359 
360 	dallocx(p, 0);
361 }
362 TEST_END
363 
364 int
main(void)365 main(void) {
366 	return test_no_reentrancy(
367 	    test_stats_summary,
368 	    test_stats_large,
369 	    test_stats_arenas_summary,
370 	    test_stats_arenas_small,
371 	    test_stats_arenas_large,
372 	    test_stats_arenas_bins,
373 	    test_stats_arenas_lextents);
374 }
375