blob: 5c4998b68bd9bc7dc0e006ecdf55237ca77aa0b4 [file] [log] [blame]
Jason Evansd82a5e62013-12-12 22:35:52 -08001#include "test/jemalloc_test.h"
2
Jason Evansfed1f9f2015-10-01 13:48:09 -07003/*
4 * Use a separate arena for xallocx() extension/contraction tests so that
5 * internal allocation e.g. by heap profiling can't interpose allocations where
6 * xallocx() would ordinarily be able to extend.
7 */
8static unsigned
9arena_ind(void)
10{
11 static unsigned ind = 0;
12
13 if (ind == 0) {
14 size_t sz = sizeof(ind);
15 assert_d_eq(mallctl("arenas.extend", &ind, &sz, NULL, 0), 0,
16 "Unexpected mallctl failure creating arena");
17 }
18
19 return (ind);
20}
21
Jason Evansd82a5e62013-12-12 22:35:52 -080022TEST_BEGIN(test_same_size)
23{
24 void *p;
25 size_t sz, tsz;
26
27 p = mallocx(42, 0);
28 assert_ptr_not_null(p, "Unexpected mallocx() error");
29 sz = sallocx(p, 0);
30
31 tsz = xallocx(p, sz, 0, 0);
32 assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
33
34 dallocx(p, 0);
35}
36TEST_END
37
38TEST_BEGIN(test_extra_no_move)
39{
40 void *p;
41 size_t sz, tsz;
42
43 p = mallocx(42, 0);
44 assert_ptr_not_null(p, "Unexpected mallocx() error");
45 sz = sallocx(p, 0);
46
47 tsz = xallocx(p, sz, sz-42, 0);
48 assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
49
50 dallocx(p, 0);
51}
52TEST_END
53
54TEST_BEGIN(test_no_move_fail)
55{
56 void *p;
57 size_t sz, tsz;
58
59 p = mallocx(42, 0);
60 assert_ptr_not_null(p, "Unexpected mallocx() error");
61 sz = sallocx(p, 0);
62
63 tsz = xallocx(p, sz + 5, 0, 0);
64 assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
65
66 dallocx(p, 0);
67}
68TEST_END
69
Jason Evans560a4e12015-09-11 16:18:53 -070070static unsigned
71get_nsizes_impl(const char *cmd)
72{
73 unsigned ret;
74 size_t z;
75
76 z = sizeof(unsigned);
77 assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
78 "Unexpected mallctl(\"%s\", ...) failure", cmd);
79
80 return (ret);
81}
82
83static unsigned
84get_nsmall(void)
85{
86
87 return (get_nsizes_impl("arenas.nbins"));
88}
89
90static unsigned
91get_nlarge(void)
92{
93
94 return (get_nsizes_impl("arenas.nlruns"));
95}
96
97static unsigned
98get_nhuge(void)
99{
100
101 return (get_nsizes_impl("arenas.nhchunks"));
102}
103
104static size_t
105get_size_impl(const char *cmd, size_t ind)
106{
107 size_t ret;
108 size_t z;
109 size_t mib[4];
110 size_t miblen = 4;
111
112 z = sizeof(size_t);
113 assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
114 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
115 mib[2] = ind;
116 z = sizeof(size_t);
117 assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
118 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
119
120 return (ret);
121}
122
123static size_t
124get_small_size(size_t ind)
125{
126
127 return (get_size_impl("arenas.bin.0.size", ind));
128}
129
130static size_t
131get_large_size(size_t ind)
132{
133
134 return (get_size_impl("arenas.lrun.0.size", ind));
135}
136
137static size_t
138get_huge_size(size_t ind)
139{
140
141 return (get_size_impl("arenas.hchunk.0.size", ind));
142}
143
Jason Evansaca490f2015-09-15 14:39:29 -0700144TEST_BEGIN(test_size)
145{
146 size_t small0, hugemax;
147 void *p;
148
149 /* Get size classes. */
150 small0 = get_small_size(0);
151 hugemax = get_huge_size(get_nhuge()-1);
152
153 p = mallocx(small0, 0);
154 assert_ptr_not_null(p, "Unexpected mallocx() error");
155
156 /* Test smallest supported size. */
157 assert_zu_eq(xallocx(p, 1, 0, 0), small0,
158 "Unexpected xallocx() behavior");
159
160 /* Test largest supported size. */
161 assert_zu_le(xallocx(p, hugemax, 0, 0), hugemax,
162 "Unexpected xallocx() behavior");
163
164 /* Test size overflow. */
165 assert_zu_le(xallocx(p, hugemax+1, 0, 0), hugemax,
166 "Unexpected xallocx() behavior");
167 assert_zu_le(xallocx(p, SIZE_T_MAX, 0, 0), hugemax,
168 "Unexpected xallocx() behavior");
169
170 dallocx(p, 0);
171}
172TEST_END
173
174TEST_BEGIN(test_size_extra_overflow)
175{
176 size_t small0, hugemax;
177 void *p;
178
179 /* Get size classes. */
180 small0 = get_small_size(0);
181 hugemax = get_huge_size(get_nhuge()-1);
182
183 p = mallocx(small0, 0);
184 assert_ptr_not_null(p, "Unexpected mallocx() error");
185
186 /* Test overflows that can be resolved by clamping extra. */
187 assert_zu_le(xallocx(p, hugemax-1, 2, 0), hugemax,
188 "Unexpected xallocx() behavior");
189 assert_zu_le(xallocx(p, hugemax, 1, 0), hugemax,
190 "Unexpected xallocx() behavior");
191
192 /* Test overflow such that hugemax-size underflows. */
193 assert_zu_le(xallocx(p, hugemax+1, 2, 0), hugemax,
194 "Unexpected xallocx() behavior");
195 assert_zu_le(xallocx(p, hugemax+2, 3, 0), hugemax,
196 "Unexpected xallocx() behavior");
197 assert_zu_le(xallocx(p, SIZE_T_MAX-2, 2, 0), hugemax,
198 "Unexpected xallocx() behavior");
199 assert_zu_le(xallocx(p, SIZE_T_MAX-1, 1, 0), hugemax,
200 "Unexpected xallocx() behavior");
201
202 dallocx(p, 0);
203}
204TEST_END
205
Jason Evans560a4e12015-09-11 16:18:53 -0700206TEST_BEGIN(test_extra_small)
207{
208 size_t small0, small1, hugemax;
209 void *p;
210
211 /* Get size classes. */
212 small0 = get_small_size(0);
213 small1 = get_small_size(1);
214 hugemax = get_huge_size(get_nhuge()-1);
215
216 p = mallocx(small0, 0);
217 assert_ptr_not_null(p, "Unexpected mallocx() error");
218
219 assert_zu_eq(xallocx(p, small1, 0, 0), small0,
220 "Unexpected xallocx() behavior");
221
222 assert_zu_eq(xallocx(p, small1, 0, 0), small0,
223 "Unexpected xallocx() behavior");
224
225 assert_zu_eq(xallocx(p, small0, small1 - small0, 0), small0,
226 "Unexpected xallocx() behavior");
227
228 /* Test size+extra overflow. */
229 assert_zu_eq(xallocx(p, small0, hugemax - small0 + 1, 0), small0,
230 "Unexpected xallocx() behavior");
231 assert_zu_eq(xallocx(p, small0, SIZE_T_MAX - small0, 0), small0,
232 "Unexpected xallocx() behavior");
233
234 dallocx(p, 0);
235}
236TEST_END
237
238TEST_BEGIN(test_extra_large)
239{
Jason Evansfed1f9f2015-10-01 13:48:09 -0700240 int flags = MALLOCX_ARENA(arena_ind());
Jason Evans560a4e12015-09-11 16:18:53 -0700241 size_t smallmax, large0, large1, large2, huge0, hugemax;
242 void *p;
243
244 /* Get size classes. */
245 smallmax = get_small_size(get_nsmall()-1);
246 large0 = get_large_size(0);
247 large1 = get_large_size(1);
248 large2 = get_large_size(2);
249 huge0 = get_huge_size(0);
250 hugemax = get_huge_size(get_nhuge()-1);
251
Jason Evansfed1f9f2015-10-01 13:48:09 -0700252 p = mallocx(large2, flags);
Jason Evans560a4e12015-09-11 16:18:53 -0700253 assert_ptr_not_null(p, "Unexpected mallocx() error");
254
Jason Evansfed1f9f2015-10-01 13:48:09 -0700255 assert_zu_eq(xallocx(p, large2, 0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700256 "Unexpected xallocx() behavior");
257 /* Test size decrease with zero extra. */
Jason Evansfed1f9f2015-10-01 13:48:09 -0700258 assert_zu_eq(xallocx(p, large0, 0, flags), large0,
Jason Evans560a4e12015-09-11 16:18:53 -0700259 "Unexpected xallocx() behavior");
Jason Evansfed1f9f2015-10-01 13:48:09 -0700260 assert_zu_eq(xallocx(p, smallmax, 0, flags), large0,
Jason Evans560a4e12015-09-11 16:18:53 -0700261 "Unexpected xallocx() behavior");
262
Jason Evansfed1f9f2015-10-01 13:48:09 -0700263 assert_zu_eq(xallocx(p, large2, 0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700264 "Unexpected xallocx() behavior");
265 /* Test size decrease with non-zero extra. */
Jason Evansfed1f9f2015-10-01 13:48:09 -0700266 assert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700267 "Unexpected xallocx() behavior");
Jason Evansfed1f9f2015-10-01 13:48:09 -0700268 assert_zu_eq(xallocx(p, large1, large2 - large1, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700269 "Unexpected xallocx() behavior");
Jason Evansfed1f9f2015-10-01 13:48:09 -0700270 assert_zu_eq(xallocx(p, large0, large1 - large0, flags), large1,
Jason Evans560a4e12015-09-11 16:18:53 -0700271 "Unexpected xallocx() behavior");
Jason Evansfed1f9f2015-10-01 13:48:09 -0700272 assert_zu_eq(xallocx(p, smallmax, large0 - smallmax, flags), large0,
Jason Evans560a4e12015-09-11 16:18:53 -0700273 "Unexpected xallocx() behavior");
274
Jason Evansfed1f9f2015-10-01 13:48:09 -0700275 assert_zu_eq(xallocx(p, large0, 0, flags), large0,
Jason Evans560a4e12015-09-11 16:18:53 -0700276 "Unexpected xallocx() behavior");
277 /* Test size increase with zero extra. */
Jason Evansfed1f9f2015-10-01 13:48:09 -0700278 assert_zu_eq(xallocx(p, large2, 0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700279 "Unexpected xallocx() behavior");
Jason Evansfed1f9f2015-10-01 13:48:09 -0700280 assert_zu_eq(xallocx(p, huge0, 0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700281 "Unexpected xallocx() behavior");
282
Jason Evansfed1f9f2015-10-01 13:48:09 -0700283 assert_zu_eq(xallocx(p, large0, 0, flags), large0,
Jason Evans560a4e12015-09-11 16:18:53 -0700284 "Unexpected xallocx() behavior");
285 /* Test size increase with non-zero extra. */
Jason Evansfed1f9f2015-10-01 13:48:09 -0700286 assert_zu_lt(xallocx(p, large0, huge0 - large0, flags), huge0,
Jason Evans560a4e12015-09-11 16:18:53 -0700287 "Unexpected xallocx() behavior");
288
Jason Evansfed1f9f2015-10-01 13:48:09 -0700289 assert_zu_eq(xallocx(p, large0, 0, flags), large0,
Jason Evans560a4e12015-09-11 16:18:53 -0700290 "Unexpected xallocx() behavior");
291 /* Test size increase with non-zero extra. */
Jason Evansfed1f9f2015-10-01 13:48:09 -0700292 assert_zu_eq(xallocx(p, large0, large2 - large0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700293 "Unexpected xallocx() behavior");
294
Jason Evansfed1f9f2015-10-01 13:48:09 -0700295 assert_zu_eq(xallocx(p, large2, 0, flags), large2,
Jason Evans560a4e12015-09-11 16:18:53 -0700296 "Unexpected xallocx() behavior");
297 /* Test size+extra overflow. */
Jason Evansfed1f9f2015-10-01 13:48:09 -0700298 assert_zu_lt(xallocx(p, large2, hugemax - large2 + 1, flags), huge0,
Jason Evans560a4e12015-09-11 16:18:53 -0700299 "Unexpected xallocx() behavior");
300
Jason Evansfed1f9f2015-10-01 13:48:09 -0700301 dallocx(p, flags);
Jason Evans560a4e12015-09-11 16:18:53 -0700302}
303TEST_END
304
305TEST_BEGIN(test_extra_huge)
306{
Jason Evansfed1f9f2015-10-01 13:48:09 -0700307 int flags = MALLOCX_ARENA(arena_ind());
Christopher Ferrise4294032016-03-02 14:33:02 -0800308 size_t largemax, huge1, huge2, huge3, hugemax;
Jason Evans560a4e12015-09-11 16:18:53 -0700309 void *p;
310
311 /* Get size classes. */
312 largemax = get_large_size(get_nlarge()-1);
Jason Evans560a4e12015-09-11 16:18:53 -0700313 huge1 = get_huge_size(1);
314 huge2 = get_huge_size(2);
Christopher Ferrise4294032016-03-02 14:33:02 -0800315 huge3 = get_huge_size(3);
Jason Evans560a4e12015-09-11 16:18:53 -0700316 hugemax = get_huge_size(get_nhuge()-1);
317
Christopher Ferrise4294032016-03-02 14:33:02 -0800318 p = mallocx(huge3, flags);
Jason Evans560a4e12015-09-11 16:18:53 -0700319 assert_ptr_not_null(p, "Unexpected mallocx() error");
320
Christopher Ferrise4294032016-03-02 14:33:02 -0800321 assert_zu_eq(xallocx(p, huge3, 0, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700322 "Unexpected xallocx() behavior");
323 /* Test size decrease with zero extra. */
Christopher Ferrise4294032016-03-02 14:33:02 -0800324 assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
Jason Evans560a4e12015-09-11 16:18:53 -0700325 "Unexpected xallocx() behavior");
Christopher Ferrise4294032016-03-02 14:33:02 -0800326 assert_zu_ge(xallocx(p, largemax, 0, flags), huge1,
Jason Evans560a4e12015-09-11 16:18:53 -0700327 "Unexpected xallocx() behavior");
328
Christopher Ferrise4294032016-03-02 14:33:02 -0800329 assert_zu_eq(xallocx(p, huge3, 0, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700330 "Unexpected xallocx() behavior");
331 /* Test size decrease with non-zero extra. */
Christopher Ferrise4294032016-03-02 14:33:02 -0800332 assert_zu_eq(xallocx(p, huge1, huge3 - huge1, flags), huge3,
333 "Unexpected xallocx() behavior");
334 assert_zu_eq(xallocx(p, huge2, huge3 - huge2, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700335 "Unexpected xallocx() behavior");
Jason Evansfed1f9f2015-10-01 13:48:09 -0700336 assert_zu_eq(xallocx(p, huge1, huge2 - huge1, flags), huge2,
Jason Evans560a4e12015-09-11 16:18:53 -0700337 "Unexpected xallocx() behavior");
Christopher Ferrise4294032016-03-02 14:33:02 -0800338 assert_zu_ge(xallocx(p, largemax, huge1 - largemax, flags), huge1,
Jason Evans560a4e12015-09-11 16:18:53 -0700339 "Unexpected xallocx() behavior");
340
Christopher Ferrise4294032016-03-02 14:33:02 -0800341 assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
Jason Evans560a4e12015-09-11 16:18:53 -0700342 "Unexpected xallocx() behavior");
343 /* Test size increase with zero extra. */
Christopher Ferrise4294032016-03-02 14:33:02 -0800344 assert_zu_le(xallocx(p, huge3, 0, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700345 "Unexpected xallocx() behavior");
Christopher Ferrise4294032016-03-02 14:33:02 -0800346 assert_zu_le(xallocx(p, hugemax+1, 0, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700347 "Unexpected xallocx() behavior");
348
Christopher Ferrise4294032016-03-02 14:33:02 -0800349 assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
Jason Evans560a4e12015-09-11 16:18:53 -0700350 "Unexpected xallocx() behavior");
351 /* Test size increase with non-zero extra. */
Christopher Ferrise4294032016-03-02 14:33:02 -0800352 assert_zu_le(xallocx(p, huge1, SIZE_T_MAX - huge1, flags), hugemax,
Jason Evans560a4e12015-09-11 16:18:53 -0700353 "Unexpected xallocx() behavior");
354
Christopher Ferrise4294032016-03-02 14:33:02 -0800355 assert_zu_ge(xallocx(p, huge1, 0, flags), huge1,
Jason Evans560a4e12015-09-11 16:18:53 -0700356 "Unexpected xallocx() behavior");
357 /* Test size increase with non-zero extra. */
Christopher Ferrise4294032016-03-02 14:33:02 -0800358 assert_zu_le(xallocx(p, huge1, huge3 - huge1, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700359 "Unexpected xallocx() behavior");
360
Christopher Ferrise4294032016-03-02 14:33:02 -0800361 assert_zu_eq(xallocx(p, huge3, 0, flags), huge3,
Jason Evans560a4e12015-09-11 16:18:53 -0700362 "Unexpected xallocx() behavior");
363 /* Test size+extra overflow. */
Christopher Ferrise4294032016-03-02 14:33:02 -0800364 assert_zu_le(xallocx(p, huge3, hugemax - huge3 + 1, flags), hugemax,
Jason Evans560a4e12015-09-11 16:18:53 -0700365 "Unexpected xallocx() behavior");
366
Jason Evansfed1f9f2015-10-01 13:48:09 -0700367 dallocx(p, flags);
Jason Evans560a4e12015-09-11 16:18:53 -0700368}
369TEST_END
370
Jason Evansd260f442015-09-24 16:38:45 -0700371static void
372print_filled_extents(const void *p, uint8_t c, size_t len)
373{
374 const uint8_t *pc = (const uint8_t *)p;
375 size_t i, range0;
376 uint8_t c0;
377
378 malloc_printf(" p=%p, c=%#x, len=%zu:", p, c, len);
379 range0 = 0;
380 c0 = pc[0];
381 for (i = 0; i < len; i++) {
382 if (pc[i] != c0) {
383 malloc_printf(" %#x[%zu..%zu)", c0, range0, i);
384 range0 = i;
385 c0 = pc[i];
386 }
387 }
388 malloc_printf(" %#x[%zu..%zu)\n", c0, range0, i);
389}
390
391static bool
392validate_fill(const void *p, uint8_t c, size_t offset, size_t len)
393{
394 const uint8_t *pc = (const uint8_t *)p;
395 bool err;
396 size_t i;
397
398 for (i = offset, err = false; i < offset+len; i++) {
399 if (pc[i] != c)
400 err = true;
401 }
402
403 if (err)
404 print_filled_extents(p, c, offset + len);
405
406 return (err);
407}
408
409static void
410test_zero(size_t szmin, size_t szmax)
411{
Jason Evansfed1f9f2015-10-01 13:48:09 -0700412 int flags = MALLOCX_ARENA(arena_ind()) | MALLOCX_ZERO;
Jason Evansd260f442015-09-24 16:38:45 -0700413 size_t sz, nsz;
414 void *p;
415#define FILL_BYTE 0x7aU
416
417 sz = szmax;
Jason Evansfed1f9f2015-10-01 13:48:09 -0700418 p = mallocx(sz, flags);
Jason Evansd260f442015-09-24 16:38:45 -0700419 assert_ptr_not_null(p, "Unexpected mallocx() error");
420 assert_false(validate_fill(p, 0x00, 0, sz), "Memory not filled: sz=%zu",
421 sz);
422
423 /*
424 * Fill with non-zero so that non-debug builds are more likely to detect
425 * errors.
426 */
427 memset(p, FILL_BYTE, sz);
428 assert_false(validate_fill(p, FILL_BYTE, 0, sz),
429 "Memory not filled: sz=%zu", sz);
430
431 /* Shrink in place so that we can expect growing in place to succeed. */
432 sz = szmin;
Jason Evansfed1f9f2015-10-01 13:48:09 -0700433 assert_zu_eq(xallocx(p, sz, 0, flags), sz,
Jason Evansd260f442015-09-24 16:38:45 -0700434 "Unexpected xallocx() error");
435 assert_false(validate_fill(p, FILL_BYTE, 0, sz),
436 "Memory not filled: sz=%zu", sz);
437
438 for (sz = szmin; sz < szmax; sz = nsz) {
Jason Evansfed1f9f2015-10-01 13:48:09 -0700439 nsz = nallocx(sz+1, flags);
440 assert_zu_eq(xallocx(p, sz+1, 0, flags), nsz,
Jason Evansd260f442015-09-24 16:38:45 -0700441 "Unexpected xallocx() failure");
442 assert_false(validate_fill(p, FILL_BYTE, 0, sz),
443 "Memory not filled: sz=%zu", sz);
444 assert_false(validate_fill(p, 0x00, sz, nsz-sz),
445 "Memory not filled: sz=%zu, nsz-sz=%zu", sz, nsz-sz);
446 memset((void *)((uintptr_t)p + sz), FILL_BYTE, nsz-sz);
447 assert_false(validate_fill(p, FILL_BYTE, 0, nsz),
448 "Memory not filled: nsz=%zu", nsz);
449 }
450
Jason Evansfed1f9f2015-10-01 13:48:09 -0700451 dallocx(p, flags);
Jason Evansd260f442015-09-24 16:38:45 -0700452}
453
454TEST_BEGIN(test_zero_large)
455{
456 size_t large0, largemax;
457
458 /* Get size classes. */
459 large0 = get_large_size(0);
460 largemax = get_large_size(get_nlarge()-1);
461
462 test_zero(large0, largemax);
463}
464TEST_END
465
466TEST_BEGIN(test_zero_huge)
467{
468 size_t huge0, huge1;
Jason Evansd260f442015-09-24 16:38:45 -0700469
470 /* Get size classes. */
471 huge0 = get_huge_size(0);
472 huge1 = get_huge_size(1);
473
Jason Evansd260f442015-09-24 16:38:45 -0700474 test_zero(huge1, huge0 * 2);
475}
476TEST_END
477
Jason Evansd82a5e62013-12-12 22:35:52 -0800478int
479main(void)
480{
481
482 return (test(
483 test_same_size,
484 test_extra_no_move,
Jason Evans560a4e12015-09-11 16:18:53 -0700485 test_no_move_fail,
Jason Evansaca490f2015-09-15 14:39:29 -0700486 test_size,
487 test_size_extra_overflow,
Jason Evans560a4e12015-09-11 16:18:53 -0700488 test_extra_small,
489 test_extra_large,
Jason Evansd260f442015-09-24 16:38:45 -0700490 test_extra_huge,
491 test_zero_large,
492 test_zero_huge));
Jason Evansd82a5e62013-12-12 22:35:52 -0800493}