The MinGW.OSDN Windows System Libraries. Formerly designated as "MinGW.org Windows System Libraries", this encapsulates the "mingwrt" C runtime library extensions, and the "w32api" 32-bit MS-Windows API libraries.
Please note that this project no longer owns the "MinGW.org" domain name; any software which may be distributed from that domain is NOT supported by this project.
修订版 | 68d05709cce24da7cfdc0177255382107953a343 (tree) |
---|---|
时间 | 2018-12-21 04:43:18 |
作者 | Keith Marshall <keith@user...> |
Commiter | Keith Marshall |
Implement test suite for aligned heap management API.
@@ -1,5 +1,13 @@ | ||
1 | 1 | 2018-12-20 Keith Marshall <keith@users.osdn.me> |
2 | 2 | |
3 | + Implement test suite for aligned heap management API. | |
4 | + | |
5 | + * tests/testsuite.at.in: Include... | |
6 | + * tests/memalign.at: ...this new file; it replaces... | |
7 | + * mingwex/tst-aligned-malloc.c: ...this; delete it. | |
8 | + | |
9 | +2018-12-20 Keith Marshall <keith@users.osdn.me> | |
10 | + | |
3 | 11 | Reimplement aligned heap management API. |
4 | 12 | |
5 | 13 | * mingwex/mingw-aligned-malloc.c: Delete it; it is replaced by... |
@@ -1,90 +0,0 @@ | ||
1 | -#include <stdio.h> | |
2 | -#include <stdlib.h> | |
3 | -#include <time.h> | |
4 | -#include <string.h> | |
5 | -#include <errno.h> | |
6 | -#include <malloc.h> | |
7 | - | |
8 | -#ifdef HAVE_STDINT_H | |
9 | -# include <stdint.h> /* uintptr_t */ | |
10 | -#else | |
11 | -# define uintptr_t size_t | |
12 | -#endif | |
13 | - | |
14 | -#define NELEM(a) (sizeof(a) / sizeof(a[0])) | |
15 | - | |
16 | -static int | |
17 | -is_aligned (void *p, size_t alignment, size_t offset) | |
18 | -{ | |
19 | - return !((((uintptr_t) p) + offset) & (alignment - 1)); | |
20 | -} | |
21 | - | |
22 | -#define MAX_SIZE (1 << sizeof(unsigned char)) | |
23 | -#define NP 1000 | |
24 | -#define NTST 100000U | |
25 | - | |
26 | -#define ERRMSG fprintf(stderr, "Iteration %u, align = %u, offset = %u, size = %u (oldsize = %u), errno = %d (%s)\n", i, align[j % NELEM(align)], offset[j % NELEM(offset)], size[j], oldsize, errno, strerror(errno)) | |
27 | - | |
28 | -int | |
29 | -main (void) | |
30 | -{ | |
31 | - unsigned char *p[NP]; | |
32 | - size_t size[NP]; | |
33 | - size_t align[] = { 2, 4, 8, 16, 32, 64 }; | |
34 | - size_t offset[20]; | |
35 | - unsigned i; | |
36 | - | |
37 | - srand (time (NULL)); | |
38 | - | |
39 | - for (i = 0; i < NELEM (p); ++i) | |
40 | - { | |
41 | - p[i] = 0; | |
42 | - size[i] = 0; | |
43 | - } | |
44 | - | |
45 | - for (i = 0; i < NELEM (offset); ++i) | |
46 | - offset[i] = rand () % 512; | |
47 | - | |
48 | - for (i = 0; i < NTST; ++i) | |
49 | - { | |
50 | - size_t oldsize; | |
51 | - unsigned j, k; | |
52 | - j = rand () % NELEM (p); | |
53 | - oldsize = size[j]; | |
54 | - p[j] = __mingw_aligned_offset_realloc (p[j], | |
55 | - size[j] = rand () % MAX_SIZE, | |
56 | - align[j % NELEM (align)], | |
57 | - offset[j % NELEM (offset)]); | |
58 | - | |
59 | - if (size[j] && !p[j]) | |
60 | - { | |
61 | - fprintf (stderr, "Returned NULL!\n"); | |
62 | - ERRMSG; | |
63 | - return EXIT_FAILURE; | |
64 | - } | |
65 | - if (size[j] && !is_aligned (p[j], | |
66 | - align[j % NELEM (align)], | |
67 | - offset[j % NELEM (offset)])) | |
68 | - { | |
69 | - fprintf (stderr, "Misaligned block!\n"); | |
70 | - ERRMSG; | |
71 | - return EXIT_FAILURE; | |
72 | - } | |
73 | - if (oldsize > size[j]) | |
74 | - oldsize = size[j]; | |
75 | - for (k = 0; k < oldsize; ++k) | |
76 | - if (p[j][k] != k) | |
77 | - { | |
78 | - fprintf (stderr, "Miscopied block!\n"); | |
79 | - ERRMSG; | |
80 | - return EXIT_FAILURE; | |
81 | - } | |
82 | - for (k = 0; k < size[j]; ++k) | |
83 | - p[j][k] = k; | |
84 | - } | |
85 | - | |
86 | - for (i = 0; i < NELEM (p); ++i) | |
87 | - __mingw_aligned_free (p[i]); | |
88 | - | |
89 | - return EXIT_SUCCESS; | |
90 | -} |
@@ -0,0 +1,487 @@ | ||
1 | +# memalign.at | |
2 | +# | |
3 | +# Autotest module to verify correct operation of the MinGW aligned | |
4 | +# heap memory management API. | |
5 | +# | |
6 | +# $Id$ | |
7 | +# | |
8 | +# Written by Keith Marshall <keith@users.osdn.me> | |
9 | +# Copyright (C) 2018, MinGW.org Project | |
10 | +# | |
11 | +# | |
12 | +# Permission is hereby granted, free of charge, to any person obtaining a | |
13 | +# copy of this software and associated documentation files (the "Software"), | |
14 | +# to deal in the Software without restriction, including without limitation | |
15 | +# the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
16 | +# and/or sell copies of the Software, and to permit persons to whom the | |
17 | +# Software is furnished to do so, subject to the following conditions: | |
18 | +# | |
19 | +# The above copyright notice and this permission notice (including the next | |
20 | +# paragraph) shall be included in all copies or substantial portions of the | |
21 | +# Software. | |
22 | +# | |
23 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
24 | +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
25 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
26 | +# AUTHORS OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
27 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
28 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
29 | +# DEALINGS IN THE SOFTWARE. | |
30 | +# | |
31 | +# | |
32 | +# All tests specified herein are written in the C language. | |
33 | +# | |
34 | +MINGW_AT_LANG([C]) | |
35 | + | |
36 | +AT_BANNER([Aligned heap memory allocation function checks.]) | |
37 | +#----------------------------------------------------------- | |
38 | +# Implement a collection of tests to exercise the MinGW aligned memory | |
39 | +# allocation functions, and confirm that they yield correcly aligned heap | |
40 | +# memory blocks, or that they fail appropriately. | |
41 | + | |
42 | +AT_SETUP([Allocation on valid alignment boundaries])dnl | |
43 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
44 | +/* Check that __mingw_aligned_malloc(), and __mingw_aligned_offset_malloc() | |
45 | + * return non-NULL pointers, which are numerically exact integer multiples of | |
46 | + * any specified alignment. Also gratuitously uses __mingw_free(), but does | |
47 | + * not verify its behaviour; this is checked independently. | |
48 | + */ | |
49 | +#include <malloc.h> | |
50 | +int main() | |
51 | +{ size_t alignment, status = 0; | |
52 | + for( alignment = 1; 128 >= alignment; alignment <<= 1 ) | |
53 | + { void *ptr = __mingw_aligned_malloc(128, alignment); | |
54 | + status |= (ptr != NULL) ? (size_t)(ptr) % alignment : 1; | |
55 | + __mingw_free(ptr); | |
56 | + ptr = __mingw_aligned_offset_malloc(128, alignment, 5); | |
57 | + status |= (ptr != NULL) ? ((size_t)(ptr) + 5) % alignment : 1; | |
58 | + __mingw_free(ptr); | |
59 | + } | |
60 | + return status; | |
61 | +}]]])dnl | |
62 | +AT_CLEANUP | |
63 | + | |
64 | +AT_SETUP([Rejection of invalid alignment specifications])dnl | |
65 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
66 | +/* Check that __mingw_aligned_malloc(), and __mingw_aligned_offset_malloc() | |
67 | + * fail, returning a NULL pointer, and setting errno to EINVAL, when called | |
68 | + * with an alignment argument which is not an integer power of two. Again, | |
69 | + * this gratuitously uses __mingw_free(), without attempting to verify its | |
70 | + * behaviour, which is checked independently. | |
71 | + */ | |
72 | +#include <malloc.h> | |
73 | +#include <errno.h> | |
74 | +int main() | |
75 | +{ size_t alignment, status = 0; | |
76 | + for( alignment = sizeof (void *); 128 >= alignment; alignment <<= 1 ) | |
77 | + { void *ptr = __mingw_aligned_malloc(128, alignment - 1); | |
78 | + if( (ptr != NULL) || (errno != EINVAL) ) status = 1; | |
79 | + __mingw_free(ptr); | |
80 | + ptr = __mingw_aligned_offset_malloc(128, alignment - 1, 5); | |
81 | + if( (ptr != NULL) || (errno != EINVAL) ) status = 1; | |
82 | + __mingw_free(ptr); | |
83 | + } | |
84 | + return status; | |
85 | +}]]])dnl | |
86 | +AT_CLEANUP | |
87 | + | |
88 | +AT_SETUP([Rejection of excessive offset specifications])dnl | |
89 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
90 | +/* Check that __mingw_aligned_offset_malloc() fails, returning a NULL | |
91 | + * pointer, and setting errno to EINVAL, when called with any value for | |
92 | + * its offset argument which is non-zero, and greater than or equal to | |
93 | + * the requested size argument. | |
94 | + */ | |
95 | +#include <malloc.h> | |
96 | +#include <errno.h> | |
97 | +int main() | |
98 | +{ size_t alignment, status = 0; | |
99 | + for( alignment = sizeof (void *); 128 >= alignment; alignment <<= 1 ) | |
100 | + { void *ptr = __mingw_aligned_offset_malloc(128, alignment, 128); | |
101 | + if( (ptr != NULL) || (errno != EINVAL) ) status = 1; | |
102 | + __mingw_free(ptr); | |
103 | + ptr = __mingw_aligned_offset_malloc(128, alignment, 132); | |
104 | + if( (ptr != NULL) || (errno != EINVAL) ) status = 1; | |
105 | + __mingw_free(ptr); | |
106 | + errno = 0; ptr = __mingw_aligned_offset_malloc(0, alignment, 0); | |
107 | + if( (ptr == NULL) && (errno == EINVAL) ) status |= 2; | |
108 | + __mingw_free(ptr); | |
109 | + } | |
110 | + return status; | |
111 | +}]]])dnl | |
112 | +AT_CLEANUP | |
113 | + | |
114 | +AT_BANNER([Aligned heap memory reallocation function checks.]) | |
115 | +#------------------------------------------------------------- | |
116 | +# Implement a collection of tests to exercise the MinGW aligned memory | |
117 | +# specific reallocation functions, and confirm that they yield correcly | |
118 | +# aligned heap memory blocks, or that they fail appropriately. | |
119 | + | |
120 | +AT_SETUP([Reallocation of specifically aligned memory])dnl | |
121 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
122 | +/* Check that __mingw_aligned_realloc(), and __mingw_aligned_offset_realloc() | |
123 | + * correctly reallocate previously allocated aligned memory blocks, preserving | |
124 | + * original block content, when called with acceptable arguments. | |
125 | + */ | |
126 | +#include <malloc.h> | |
127 | +#include <string.h> | |
128 | +int main() | |
129 | +{ size_t alignment, status = 0; | |
130 | + for( alignment = 1; 128 >= alignment; alignment <<= 1 ) | |
131 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size; | |
132 | + for( size = 32; 256 >= size; size <<= 1 ) | |
133 | + { if( (p3 = __mingw_aligned_realloc( p1, size, alignment)) != NULL ) | |
134 | + { p1 = p3; | |
135 | + if( p2 == NULL ) { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); } | |
136 | + status |= p2 ? strcmp( p1, p2 ) | ((size_t)(p1) % alignment) : 1; | |
137 | + } | |
138 | + else status |= 1; | |
139 | + } | |
140 | + __mingw_free(p1); __mingw_free(p2); | |
141 | + } | |
142 | + for( alignment = 1; 128 >= alignment; alignment <<= 1 ) | |
143 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size; | |
144 | + for( size = 32; 256 >= size; size <<= 1 ) | |
145 | + { if( (p3 = __mingw_aligned_offset_realloc( p1, size, alignment, 5)) != NULL ) | |
146 | + { p1 = p3; | |
147 | + if( p2 == NULL ) { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); } | |
148 | + status |= p2 ? strcmp( p1, p2 ) | (((size_t)(p1) + 5) % alignment) : 1; | |
149 | + } | |
150 | + else status |= 1; | |
151 | + } | |
152 | + __mingw_free(p1); __mingw_free(p2); | |
153 | + } | |
154 | + return status; | |
155 | +}]]])dnl | |
156 | +AT_CLEANUP | |
157 | + | |
158 | +AT_SETUP([Offset constrained rejection of size reduction])dnl | |
159 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
160 | +/* Check that __mingw_aligned_offset_realloc() correctly rejects an attempt | |
161 | + * to reduce the size of a previously offset-aligned memory block, when the | |
162 | + * resultant size will be insufficient to accommodate the specified offset; | |
163 | + * such rejection must be indicated by returning a NULL pointer, with errno | |
164 | + * set to EINVAL. | |
165 | + */ | |
166 | +#include <malloc.h> | |
167 | +#include <string.h> | |
168 | +#include <errno.h> | |
169 | +int main() | |
170 | +{ size_t align, status = 0; | |
171 | + for( align = 1; 128 >= align; align <<= 1 ) | |
172 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size; | |
173 | + for( size = 128; size > 0; size >>= 1 ) | |
174 | + { if( (p3 = __mingw_aligned_offset_realloc( p1, size, align, 16)) != NULL ) | |
175 | + { if( p3 != p1 ) p1 = p3; | |
176 | + if( p2 == NULL ) { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); } | |
177 | + status |= p2 ? strcmp( p1, p2 ) | (((size_t)(p1) + 16) % align) : 2; | |
178 | + if( 16 >= size ) status |= 1; | |
179 | + } | |
180 | + else if( (p2 == NULL) || (errno != EINVAL) ) status |= 4; | |
181 | + } | |
182 | + __mingw_free(p1); __mingw_free(p2); | |
183 | + } | |
184 | + return status; | |
185 | +}]]])dnl | |
186 | +AT_CLEANUP | |
187 | + | |
188 | +AT_SETUP([Rejection of alignment specification changes])dnl | |
189 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
190 | +/* Check that __mingw_aligned_realloc(), and __mingw_aligned_offset_realloc() | |
191 | + * fail, returning a NULL pointer, and setting errno to EINVAL, when called | |
192 | + * with an alignment parameter which differs from that originally specified, | |
193 | + * when the aligned memory block was first allocated. | |
194 | + */ | |
195 | +#include <malloc.h> | |
196 | +#include <string.h> | |
197 | +#include <errno.h> | |
198 | +int main() | |
199 | +{ size_t alignment, status = 0; | |
200 | + for( alignment = 8; 128 >= alignment; alignment <<= 1 ) | |
201 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size, align; | |
202 | + for( size = 128, align = alignment; 256 >= size; size <<= 1, align <<= 1 ) | |
203 | + { if( (p3 = __mingw_aligned_realloc( p1, size, align)) != NULL ) | |
204 | + { p1 = p3; | |
205 | + if( p2 == NULL ) | |
206 | + { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); | |
207 | + status |= p2 ? strcmp( p1, p2 ) | ((size_t)(p1) % align) : 2; | |
208 | + } | |
209 | + else status |= 1; | |
210 | + } | |
211 | + else if( (p2 == NULL) || (errno != EINVAL) ) status |= 4; | |
212 | + } | |
213 | + __mingw_free(p1); __mingw_free(p2); | |
214 | + } | |
215 | + for( alignment = 8; 128 >= alignment; alignment <<= 1 ) | |
216 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size, align; | |
217 | + for( size = 128, align = alignment; 256 >= size; size <<= 1, align <<= 1 ) | |
218 | + { if( (p3 = __mingw_aligned_offset_realloc( p1, size, align, 5)) != NULL ) | |
219 | + { p1 = p3; | |
220 | + if( p2 == NULL ) | |
221 | + { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); | |
222 | + status |= p2 ? strcmp( p1, p2 ) | (((size_t)(p1) + 5) % align) : 2; | |
223 | + } | |
224 | + else status |= 1; | |
225 | + } | |
226 | + else if( (p2 == NULL) || (errno != EINVAL) ) status |= 4; | |
227 | + } | |
228 | + __mingw_free(p1); __mingw_free(p2); | |
229 | + } | |
230 | + return status; | |
231 | +}]]])dnl | |
232 | +AT_CLEANUP | |
233 | + | |
234 | +AT_SETUP([Rejection of offset specification changes])dnl | |
235 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
236 | +/* Check that __mingw_aligned_offset_realloc() fails, returning a NULL | |
237 | + * pointer, and setting errno to EINVAL, when called an offset parameter | |
238 | + * which differs from that specified when the offset-aligned memory block | |
239 | + * was originally allocated. | |
240 | + */ | |
241 | +#include <malloc.h> | |
242 | +#include <string.h> | |
243 | +#include <errno.h> | |
244 | +int main() | |
245 | +{ size_t align, status = 0; | |
246 | + for( align = 1; 128 >= align; align <<= 1 ) | |
247 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size, offset; | |
248 | + for( size = 128, offset = 4; 256 >= size; size <<= 1, offset <<= 1 ) | |
249 | + { if( (p3 = __mingw_aligned_offset_realloc( p1, size, align, offset)) != NULL ) | |
250 | + { if( p3 != p1 ) p1 = p3; | |
251 | + if( p2 == NULL ) | |
252 | + { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); | |
253 | + status |= p2 ? strcmp( p1, p2 ) | (((size_t)(p1) + offset) % align) : 2; | |
254 | + } | |
255 | + else status |= 1; | |
256 | + } | |
257 | + else if( (p2 == NULL) || (errno != EINVAL) ) status |= 4; | |
258 | + } | |
259 | + __mingw_free(p1); __mingw_free(p2); | |
260 | + } | |
261 | + return status; | |
262 | +}]]])dnl | |
263 | +AT_CLEANUP | |
264 | + | |
265 | +AT_BANNER([Universal heap memory reallocation function checks.]) | |
266 | +#--------------------------------------------------------------- | |
267 | +# Implement a collection of tests to exercise the MinGW generic memory | |
268 | +# reallocation function, __mingw_realloc(), to confirm that it correctly | |
269 | +# discriminates between aligned and regular memory blocks, yields correcly | |
270 | +# aligned memory blocks, when appropriate, or that it fails correctly, | |
271 | +# when expected. | |
272 | +# | |
273 | +AT_SETUP([Reallocation of specifically aligned memory])dnl | |
274 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
275 | +/* Check that __mingw_realloc() can successfully resize an initially | |
276 | + * offset-aligned memory block, preserving its alignment, its offset, | |
277 | + * and its content. | |
278 | + */ | |
279 | +#include <malloc.h> | |
280 | +#include <string.h> | |
281 | +int main() | |
282 | +{ size_t align, status = 0; | |
283 | + for( align = 1; 128 >= align; align <<= 1 ) | |
284 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size = 64; | |
285 | + if( (p1 = __mingw_aligned_offset_malloc( size, align, 16)) != NULL ) | |
286 | + { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); | |
287 | + for( size = 128; 512 >= size; size <<= 1 ) | |
288 | + if( (p3 = __mingw_realloc( p1, size )) != NULL ) | |
289 | + { p1 = p3; | |
290 | + status |= p2 ? strcmp( p1, p2 ) | (((size_t)(p1) + 16) % align) : 2; | |
291 | + } | |
292 | + else status |= 1; | |
293 | + } | |
294 | + __mingw_free(p1); __mingw_free(p2); | |
295 | + } | |
296 | + return status; | |
297 | +}]]])dnl | |
298 | +AT_CLEANUP | |
299 | + | |
300 | +AT_SETUP([Reallocation of conventionally aligned memory])dnl | |
301 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
302 | +/* Check that __mingw_realloc() can successfully resize a memory block | |
303 | + * which was originally allocated by malloc(), preserving * its content, | |
304 | + * but with neither alignment nor offset constraint. | |
305 | + */ | |
306 | +#include <malloc.h> | |
307 | +#include <string.h> | |
308 | +int main() | |
309 | +{ size_t align, status = 0; | |
310 | + for( align = 1; 128 >= align; align <<= 1 ) | |
311 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size = 64; | |
312 | + if( (p1 = malloc( size )) != NULL ) | |
313 | + { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); | |
314 | + for( size = 128; 512 >= size; size <<= 1 ) | |
315 | + if( (p3 = __mingw_realloc( p1, size )) != NULL ) | |
316 | + { p1 = p3; status |= p2 ? strcmp( p1, p2 ) : 2; } | |
317 | + else status |= 1; | |
318 | + } | |
319 | + __mingw_free(p1); __mingw_free(p2); | |
320 | + } | |
321 | + return status; | |
322 | +}]]])dnl | |
323 | +AT_CLEANUP | |
324 | + | |
325 | +AT_SETUP([Offset constrained rejection of size reduction])dnl | |
326 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
327 | +/* Check that __mingw_realloc() will decline to resize an originally | |
328 | + * offset-aligned memory block, when the requested size is insufficient | |
329 | + * to accommodate any data beyond the original offset; the returned | |
330 | + * pointer must be NULL, and errno must be set to EINVAL. | |
331 | + */ | |
332 | +#include <malloc.h> | |
333 | +#include <string.h> | |
334 | +#include <errno.h> | |
335 | +int main() | |
336 | +{ size_t align, status = 0; | |
337 | + for( align = 1; 128 >= align; align <<= 1 ) | |
338 | + { void *p1 = NULL, *p2 = NULL, *p3; size_t size = 128; | |
339 | + if( (p1 = __mingw_aligned_offset_malloc( size, align, 16)) != NULL ) | |
340 | + { strcpy( p1, "Sample text." ); p2 = strdup( p1 ); | |
341 | + for( size = 64; size > 0; size >>= 1 ) | |
342 | + if( (p3 = __mingw_realloc( p1, size )) != NULL ) | |
343 | + { p1 = p3; | |
344 | + status |= p2 ? strcmp( p1, p2 ) | (((size_t)(p1) + 16) % align) : 2; | |
345 | + if( 16 >= size ) status |= 1; | |
346 | + } | |
347 | + else if( (p2 == NULL) || (errno != EINVAL) ) status |= 4; | |
348 | + } | |
349 | + __mingw_free(p1); __mingw_free(p2); | |
350 | + } | |
351 | + return status; | |
352 | +}]]])dnl | |
353 | +AT_CLEANUP | |
354 | + | |
355 | +AT_BANNER([Universal heap memory deallocation function checks.]) | |
356 | +#--------------------------------------------------------------- | |
357 | +# Implement a collection of tests to exercise the MinGW generic memory | |
358 | +# deallocation function, to confirm that it can successfully return both | |
359 | +# conventionally allocated and specifically aligned memory to the unused | |
360 | +# heap memory pool; additionally, confirm that any of the reallocation | |
361 | +# functions will perform a similar function, when allocation size is | |
362 | +# reduced to zero. | |
363 | + | |
364 | +# MINGW_AT_SKIP_IF_NO_HEAPWALK | |
365 | +# ---------------------------- | |
366 | +# Check that the host operating system supports Microsoft's _heapwalk() | |
367 | +# API; (WinNT should do, but Win9x apparently doesn't). For those which | |
368 | +# don't, indicate that dependent tests should be skipped. | |
369 | +# | |
370 | +m4_define([MINGW_AT_SKIP_IF_NO_HEAPWALK],dnl) | |
371 | +[ _HEAPINFO hmon = {NULL, 0, 0}; | |
372 | + errno = 0; int status = _heapwalk( &hmon ); | |
373 | + if( errno == ENOSYS ) return 77;dnl | |
374 | +])# MINGW_AT_SKIP_IF_NO_HEAPWALK | |
375 | + | |
376 | +# MINGW_AT_VERIFY_ALIGNED_FREE( NAME, METHOD ) | |
377 | +# -------------------------------------------- | |
378 | +# Provide a function, try_NAME(), to walk the heap, identifying the base | |
379 | +# address of the heap block, if any, which contains a specified (possibly | |
380 | +# aligned) heap pointer; invoke METHOD on the specified pointer, then walk | |
381 | +# the heap again, to confirm that the original base address either refers | |
382 | +# to an unused heap region, or it no longer refers to any heap region, | |
383 | +# in either used or unused state, which remains addressable. | |
384 | +# | |
385 | +m4_define([MINGW_AT_VERIFY_ALIGNED_FREE],[dnl | |
386 | +int try_$1( void *ptr ) | |
387 | +{ _HEAPINFO hmon = {NULL, 0, 0}; | |
388 | + if( ptr == NULL ) return 1; | |
389 | + while( _heapwalk( &hmon ) == _HEAPOK ) | |
390 | + { uintptr_t base = (uintptr_t)(hmon._pentry); | |
391 | + if( ((uintptr_t)(ptr) >= base) && ((base + hmon._size) >= (uintptr_t)(ptr)) ) | |
392 | + { if( hmon._useflag != _USEDENTRY ) return 1; | |
393 | + $2; ptr = hmon._pentry; hmon._pentry = NULL; | |
394 | + while( _heapwalk( &hmon ) == _HEAPOK ) | |
395 | + if( hmon._pentry == ptr ) return (hmon._useflag == _FREEENTRY) ? 0 : 1; | |
396 | + return 0; | |
397 | + } | |
398 | + } | |
399 | + return 1; | |
400 | +} | |
401 | +])# MINGW_AT_VERIFY_ALIGNED_FREE | |
402 | + | |
403 | +AT_SETUP([Free conventionally aligned heap memory])dnl | |
404 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
405 | +/* Check that __mingw_free() can correctly identify a pointer which | |
406 | + * was NOT allocated by any MinGW aligned memory allocation function; | |
407 | + * when any such pointer can be mapped to a heap block which may have | |
408 | + * been allocated by malloc(), or realloc(), free it regardless, and | |
409 | + * confirm that it is successfully deallocated. | |
410 | + */ | |
411 | +#include <stdint.h> | |
412 | +#include <malloc.h> | |
413 | +#include <errno.h> | |
414 | +]MINGW_AT_VERIFY_ALIGNED_FREE([free],[__mingw_free(ptr)])[ | |
415 | +int main() | |
416 | +{ size_t alignment; | |
417 | + ]MINGW_AT_SKIP_IF_NO_HEAPWALK[ | |
418 | + for( alignment = 1; 128 >= alignment; alignment <<= 1 ) | |
419 | + { if( try_free(malloc(128)) ) return 99; } | |
420 | + return 0; | |
421 | +}]]])dnl | |
422 | +AT_CLEANUP | |
423 | + | |
424 | +AT_SETUP([Free specifically aligned heap memory])dnl | |
425 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
426 | +/* Check that __mingw_free() can correctly identify a pointer which | |
427 | + * WAS allocated by a MinGW aligned memory allocation function; when | |
428 | + * any such pointer has been identified, free its underlying heap | |
429 | + * memory, and confirm that deallocation is successful. | |
430 | + */ | |
431 | +#include <stdint.h> | |
432 | +#include <malloc.h> | |
433 | +#include <errno.h> | |
434 | +]MINGW_AT_VERIFY_ALIGNED_FREE([free],[__mingw_free(ptr)])[ | |
435 | +int main() | |
436 | +{ size_t alignment; | |
437 | + ]MINGW_AT_SKIP_IF_NO_HEAPWALK[ | |
438 | + for( alignment = 1; 128 >= alignment; alignment <<= 1 ) | |
439 | + { if( try_free(__mingw_aligned_malloc(128, alignment)) ) return 99; | |
440 | + if( try_free(__mingw_aligned_offset_malloc(128, alignment, 5)) ) return 99; | |
441 | + } | |
442 | + return 0; | |
443 | +}]]])dnl | |
444 | +AT_CLEANUP | |
445 | + | |
446 | +AT_SETUP([Free by reallocation to zero size])dnl | |
447 | +AT_KEYWORDS([C memalign])MINGW_AT_CHECK_RUN([[[ | |
448 | +/* Check that __mingw_realloc() can reproduce the effect of __mingw_free(), | |
449 | + * in respect of any heap memory allocation, when called with a requested size | |
450 | + * of zero; similarly, check that each of the __mingw_aligned_realloc(), and | |
451 | + * __mingw_aligned_offset_realloc() functions reproduce the same effect, when | |
452 | + * invoked to request resizing to zero, on blocks with correspondingly matched | |
453 | + * alignment, and offset arguments. | |
454 | + * | |
455 | + * Note that this is a Microsoft compatibility check; hopefully, no user | |
456 | + * will ever write code which depends on this anomalous behaviour. | |
457 | + */ | |
458 | +#include <stdint.h> | |
459 | +#include <malloc.h> | |
460 | +#include <errno.h> | |
461 | +size_t alignment; | |
462 | +]MINGW_AT_VERIFY_ALIGNED_FREE([realloc],dnl | |
463 | +[__mingw_realloc(ptr,0)])[ | |
464 | +]MINGW_AT_VERIFY_ALIGNED_FREE([aligned_realloc],dnl | |
465 | +[__mingw_aligned_realloc(ptr,0,alignment)])[ | |
466 | +]MINGW_AT_VERIFY_ALIGNED_FREE([offset_realloc],dnl | |
467 | +[__mingw_aligned_offset_realloc(ptr,0,alignment,5)])[ | |
468 | +int main() | |
469 | +{]MINGW_AT_SKIP_IF_NO_HEAPWALK[ | |
470 | + for( alignment = 1; 128 >= alignment; alignment <<= 1 ) | |
471 | + { if( try_realloc(__mingw_aligned_malloc(128, alignment)) ) | |
472 | + return 99; | |
473 | + if( try_realloc(__mingw_aligned_offset_malloc(128, alignment, 5)) ) | |
474 | + return 99; | |
475 | + if( try_offset_realloc(__mingw_aligned_offset_malloc(128, alignment, 5)) ) | |
476 | + return 99; | |
477 | + if( try_aligned_realloc(__mingw_aligned_malloc(128, alignment)) ) | |
478 | + return 99; | |
479 | + if( try_realloc(malloc(128)) ) | |
480 | + return 99; | |
481 | + } | |
482 | + return 0; | |
483 | +}]]])dnl | |
484 | +AT_CLEANUP | |
485 | + | |
486 | +# vim: filetype=config formatoptions=croql | |
487 | +# $RCSfile$: end of file |
@@ -91,6 +91,7 @@ m4_include([ansiprintf.at]) | ||
91 | 91 | m4_include([logarithms.at]) |
92 | 92 | m4_include([powerfunc.at]) |
93 | 93 | m4_include([clockapi.at]) |
94 | +m4_include([memalign.at]) | |
94 | 95 | |
95 | 96 | # vim: filetype=config formatoptions=croql |
96 | 97 | # $RCSfile$: end of file |