• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "test/jemalloc_test.h"
2 
3 static unsigned
get_nsizes_impl(const char * cmd)4 get_nsizes_impl(const char *cmd)
5 {
6 	unsigned ret;
7 	size_t z;
8 
9 	z = sizeof(unsigned);
10 	assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
11 	    "Unexpected mallctl(\"%s\", ...) failure", cmd);
12 
13 	return (ret);
14 }
15 
16 static unsigned
get_nhuge(void)17 get_nhuge(void)
18 {
19 
20 	return (get_nsizes_impl("arenas.nhchunks"));
21 }
22 
23 static size_t
get_size_impl(const char * cmd,size_t ind)24 get_size_impl(const char *cmd, size_t ind)
25 {
26 	size_t ret;
27 	size_t z;
28 	size_t mib[4];
29 	size_t miblen = 4;
30 
31 	z = sizeof(size_t);
32 	assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
33 	    0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
34 	mib[2] = ind;
35 	z = sizeof(size_t);
36 	assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
37 	    0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
38 
39 	return (ret);
40 }
41 
42 static size_t
get_huge_size(size_t ind)43 get_huge_size(size_t ind)
44 {
45 
46 	return (get_size_impl("arenas.hchunk.0.size", ind));
47 }
48 
TEST_BEGIN(test_grow_and_shrink)49 TEST_BEGIN(test_grow_and_shrink)
50 {
51 	void *p, *q;
52 	size_t tsz;
53 #define	NCYCLES 3
54 	unsigned i, j;
55 #define	NSZS 2500
56 	size_t szs[NSZS];
57 #define	MAXSZ ZU(12 * 1024 * 1024)
58 
59 	p = mallocx(1, 0);
60 	assert_ptr_not_null(p, "Unexpected mallocx() error");
61 	szs[0] = sallocx(p, 0);
62 
63 	for (i = 0; i < NCYCLES; i++) {
64 		for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {
65 			q = rallocx(p, szs[j-1]+1, 0);
66 			assert_ptr_not_null(q,
67 			    "Unexpected rallocx() error for size=%zu-->%zu",
68 			    szs[j-1], szs[j-1]+1);
69 			szs[j] = sallocx(q, 0);
70 			assert_zu_ne(szs[j], szs[j-1]+1,
71 			    "Expected size to be at least: %zu", szs[j-1]+1);
72 			p = q;
73 		}
74 
75 		for (j--; j > 0; j--) {
76 			q = rallocx(p, szs[j-1], 0);
77 			assert_ptr_not_null(q,
78 			    "Unexpected rallocx() error for size=%zu-->%zu",
79 			    szs[j], szs[j-1]);
80 			tsz = sallocx(q, 0);
81 			assert_zu_eq(tsz, szs[j-1],
82 			    "Expected size=%zu, got size=%zu", szs[j-1], tsz);
83 			p = q;
84 		}
85 	}
86 
87 	dallocx(p, 0);
88 #undef MAXSZ
89 #undef NSZS
90 #undef NCYCLES
91 }
92 TEST_END
93 
94 static bool
validate_fill(const void * p,uint8_t c,size_t offset,size_t len)95 validate_fill(const void *p, uint8_t c, size_t offset, size_t len)
96 {
97 	bool ret = false;
98 	const uint8_t *buf = (const uint8_t *)p;
99 	size_t i;
100 
101 	for (i = 0; i < len; i++) {
102 		uint8_t b = buf[offset+i];
103 		if (b != c) {
104 			test_fail("Allocation at %p (len=%zu) contains %#x "
105 			    "rather than %#x at offset %zu", p, len, b, c,
106 			    offset+i);
107 			ret = true;
108 		}
109 	}
110 
111 	return (ret);
112 }
113 
TEST_BEGIN(test_zero)114 TEST_BEGIN(test_zero)
115 {
116 	void *p, *q;
117 	size_t psz, qsz, i, j;
118 	size_t start_sizes[] = {1, 3*1024, 63*1024, 4095*1024};
119 #define	FILL_BYTE 0xaaU
120 #define	RANGE 2048
121 
122 	for (i = 0; i < sizeof(start_sizes)/sizeof(size_t); i++) {
123 		size_t start_size = start_sizes[i];
124 		p = mallocx(start_size, MALLOCX_ZERO);
125 		assert_ptr_not_null(p, "Unexpected mallocx() error");
126 		psz = sallocx(p, 0);
127 
128 		assert_false(validate_fill(p, 0, 0, psz),
129 		    "Expected zeroed memory");
130 		memset(p, FILL_BYTE, psz);
131 		assert_false(validate_fill(p, FILL_BYTE, 0, psz),
132 		    "Expected filled memory");
133 
134 		for (j = 1; j < RANGE; j++) {
135 			q = rallocx(p, start_size+j, MALLOCX_ZERO);
136 			assert_ptr_not_null(q, "Unexpected rallocx() error");
137 			qsz = sallocx(q, 0);
138 			if (q != p || qsz != psz) {
139 				assert_false(validate_fill(q, FILL_BYTE, 0,
140 				    psz), "Expected filled memory");
141 				assert_false(validate_fill(q, 0, psz, qsz-psz),
142 				    "Expected zeroed memory");
143 			}
144 			if (psz != qsz) {
145 				memset((void *)((uintptr_t)q+psz), FILL_BYTE,
146 				    qsz-psz);
147 				psz = qsz;
148 			}
149 			p = q;
150 		}
151 		assert_false(validate_fill(p, FILL_BYTE, 0, psz),
152 		    "Expected filled memory");
153 		dallocx(p, 0);
154 	}
155 #undef FILL_BYTE
156 }
157 TEST_END
158 
TEST_BEGIN(test_align)159 TEST_BEGIN(test_align)
160 {
161 	void *p, *q;
162 	size_t align;
163 #define	MAX_ALIGN (ZU(1) << 25)
164 
165 	align = ZU(1);
166 	p = mallocx(1, MALLOCX_ALIGN(align));
167 	assert_ptr_not_null(p, "Unexpected mallocx() error");
168 
169 	for (align <<= 1; align <= MAX_ALIGN; align <<= 1) {
170 		q = rallocx(p, 1, MALLOCX_ALIGN(align));
171 		assert_ptr_not_null(q,
172 		    "Unexpected rallocx() error for align=%zu", align);
173 		assert_ptr_null(
174 		    (void *)((uintptr_t)q & (align-1)),
175 		    "%p inadequately aligned for align=%zu",
176 		    q, align);
177 		p = q;
178 	}
179 	dallocx(p, 0);
180 #undef MAX_ALIGN
181 }
182 TEST_END
183 
TEST_BEGIN(test_lg_align_and_zero)184 TEST_BEGIN(test_lg_align_and_zero)
185 {
186 	void *p, *q;
187 	unsigned lg_align;
188 	size_t sz;
189 #define	MAX_LG_ALIGN 25
190 #define	MAX_VALIDATE (ZU(1) << 22)
191 
192 	lg_align = 0;
193 	p = mallocx(1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);
194 	assert_ptr_not_null(p, "Unexpected mallocx() error");
195 
196 	for (lg_align++; lg_align <= MAX_LG_ALIGN; lg_align++) {
197 		q = rallocx(p, 1, MALLOCX_LG_ALIGN(lg_align)|MALLOCX_ZERO);
198 		assert_ptr_not_null(q,
199 		    "Unexpected rallocx() error for lg_align=%u", lg_align);
200 		assert_ptr_null(
201 		    (void *)((uintptr_t)q & ((ZU(1) << lg_align)-1)),
202 		    "%p inadequately aligned for lg_align=%u", q, lg_align);
203 		sz = sallocx(q, 0);
204 		if ((sz << 1) <= MAX_VALIDATE) {
205 			assert_false(validate_fill(q, 0, 0, sz),
206 			    "Expected zeroed memory");
207 		} else {
208 			assert_false(validate_fill(q, 0, 0, MAX_VALIDATE),
209 			    "Expected zeroed memory");
210 			assert_false(validate_fill(
211 			    (void *)((uintptr_t)q+sz-MAX_VALIDATE),
212 			    0, 0, MAX_VALIDATE), "Expected zeroed memory");
213 		}
214 		p = q;
215 	}
216 	dallocx(p, 0);
217 #undef MAX_VALIDATE
218 #undef MAX_LG_ALIGN
219 }
220 TEST_END
221 
TEST_BEGIN(test_overflow)222 TEST_BEGIN(test_overflow)
223 {
224 	size_t hugemax;
225 	void *p;
226 
227 	hugemax = get_huge_size(get_nhuge()-1);
228 
229 	p = mallocx(1, 0);
230 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
231 
232 	assert_ptr_null(rallocx(p, hugemax+1, 0),
233 	    "Expected OOM for rallocx(p, size=%#zx, 0)", hugemax+1);
234 
235 	assert_ptr_null(rallocx(p, ZU(PTRDIFF_MAX)+1, 0),
236 	    "Expected OOM for rallocx(p, size=%#zx, 0)", ZU(PTRDIFF_MAX)+1);
237 
238 	assert_ptr_null(rallocx(p, SIZE_T_MAX, 0),
239 	    "Expected OOM for rallocx(p, size=%#zx, 0)", SIZE_T_MAX);
240 
241 	assert_ptr_null(rallocx(p, 1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)),
242 	    "Expected OOM for rallocx(p, size=1, MALLOCX_ALIGN(%#zx))",
243 	    ZU(PTRDIFF_MAX)+1);
244 
245 	dallocx(p, 0);
246 }
247 TEST_END
248 
249 int
main(void)250 main(void)
251 {
252 
253 	return (test(
254 	    test_grow_and_shrink,
255 	    test_zero,
256 	    test_align,
257 	    test_lg_align_and_zero,
258 	    test_overflow));
259 }
260