2 * @file mingw-aligned-malloc.c
3 * @copy 2012 MinGW.org project
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
26 #include <stddef.h> /* ptrdiff_t */
27 #include <string.h> /* memmove */
30 # include <stdint.h> /* uintptr_t */
32 # define uintptr_t size_t
35 #define NOT_POWER_OF_TWO(n) (((n) & ((n) - 1)))
36 #define UI(p) ((uintptr_t) (p))
37 #define CP(p) ((char *) p)
39 #define PTR_ALIGN(p0, alignment, offset) \
40 ((void *) (((UI(p0) + (alignment + sizeof(void*)) + offset) \
41 & (~UI(alignment - 1))) \
44 /* Pointer must sometimes be aligned; assume sizeof(void*) is a power of two. */
45 #define ORIG_PTR(p) (*(((void **) (UI(p) & (~UI(sizeof(void*) - 1)))) - 1))
48 __mingw_aligned_offset_malloc (size_t size, size_t alignment, size_t offset)
52 if (NOT_POWER_OF_TWO (alignment))
59 if (alignment < sizeof (void *))
60 alignment = sizeof (void *);
62 /* Including the extra sizeof(void*) is overkill on a 32-bit
63 machine, since malloc is already 8-byte aligned, as long
64 as we enforce alignment >= 8 ...but oh well. */
66 p0 = malloc (size + (alignment + sizeof (void *)));
69 p = PTR_ALIGN (p0, alignment, offset);
75 __mingw_aligned_malloc (size_t size, size_t alignment)
77 return __mingw_aligned_offset_malloc (size, alignment, 0);
81 __mingw_aligned_free (void *memblock)
84 free (ORIG_PTR (memblock));
88 __mingw_aligned_offset_realloc (void *memblock, size_t size,
89 size_t alignment, size_t offset)
95 return __mingw_aligned_offset_malloc (size, alignment, offset);
96 if (NOT_POWER_OF_TWO (alignment))
100 __mingw_aligned_free (memblock);
103 if (alignment < sizeof (void *))
104 alignment = sizeof (void *);
106 p0 = ORIG_PTR (memblock);
107 /* It is an error for the alignment to change. */
108 if (memblock != PTR_ALIGN (p0, alignment, offset))
110 shift = CP (memblock) - CP (p0);
112 p0 = realloc (p0, size + (alignment + sizeof (void *)));
115 p = PTR_ALIGN (p0, alignment, offset);
117 /* Relative shift of actual data may be different from before, ugh. */
118 if (shift != CP (p) - CP (p0))
119 /* ugh, moves more than necessary if size is increased. */
120 memmove (CP (p), CP (p0) + shift, size);
131 __mingw_aligned_realloc (void *memblock, size_t size, size_t alignment)
133 return __mingw_aligned_offset_realloc (memblock, size, alignment, 0);