diff options
author | Danny Smith <dannysmith@users.sourceforge.net> | 2004-08-24 08:55:42 +0000 |
---|---|---|
committer | Danny Smith <dannysmith@users.sourceforge.net> | 2004-08-24 08:55:42 +0000 |
commit | a6c2ea7e7c363f691fc4dc683c0772b3dab2db70 (patch) | |
tree | 2dcf0f2de94d02565181d94366cab207d200fa37 /winsup/mingw/mingwex/mingw-aligned-malloc.c | |
parent | 45b1139e413d3939436dac636991a5bbbfd7e9ad (diff) | |
download | cygnal-a6c2ea7e7c363f691fc4dc683c0772b3dab2db70.tar.gz cygnal-a6c2ea7e7c363f691fc4dc683c0772b3dab2db70.tar.bz2 cygnal-a6c2ea7e7c363f691fc4dc683c0772b3dab2db70.zip |
2004-08-24 Steven G. Johnson <stevenj@alum.mit.edu>
* mingwex/mingw-aligned-malloc.c: New file.
* mingwex/tst-aligned-malloc.c: New file.
Diffstat (limited to 'winsup/mingw/mingwex/mingw-aligned-malloc.c')
-rwxr-xr-x | winsup/mingw/mingwex/mingw-aligned-malloc.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/winsup/mingw/mingwex/mingw-aligned-malloc.c b/winsup/mingw/mingwex/mingw-aligned-malloc.c new file mode 100755 index 000000000..a6d4ac934 --- /dev/null +++ b/winsup/mingw/mingwex/mingw-aligned-malloc.c @@ -0,0 +1,120 @@ +/* + __mingw_aligned_malloc and friends, implemented using Microsoft's public + interfaces and with the help of the algorithm description provided + by Wu Yongwei: http://sourceforge.net/mailarchive/message.php?msg_id=3847075 + + I hereby place this implementation in the public domain. + -- Steven G. Johnson (stevenj@alum.mit.edu) +*/ + +#include <stdlib.h> +#include <errno.h> +#include <stddef.h> /* ptrdiff_t */ +#include <string.h> /* memmove */ + +#ifdef HAVE_STDINT_H +# include <stdint.h> /* uintptr_t */ +#else +# define uintptr_t size_t +#endif + +#define NOT_POWER_OF_TWO(n) (((n) & ((n) - 1))) +#define UI(p) ((uintptr_t) (p)) +#define CP(p) ((char *) p) + +#define PTR_ALIGN(p0, alignment, offset) \ + ((void *) (((UI(p0) + (alignment + sizeof(void*)) + offset) \ + & (~UI(alignment - 1))) \ + - offset)) + +/* Pointer must sometimes be aligned; assume sizeof(void*) is a power of two. */ +#define ORIG_PTR(p) (*(((void **) (UI(p) & (~UI(sizeof(void*) - 1)))) - 1)) + +void * +__mingw_aligned_offset_malloc (size_t size, size_t alignment, size_t offset) +{ + void *p0, *p; + + if (NOT_POWER_OF_TWO (alignment)) + { + errno = EINVAL; + return ((void *) 0); + } + if (size == 0) + return ((void *) 0); + if (alignment < sizeof (void *)) + alignment = sizeof (void *); + + /* Including the extra sizeof(void*) is overkill on a 32-bit + machine, since malloc is already 8-byte aligned, as long + as we enforce alignment >= 8 ...but oh well. */ + + p0 = malloc (size + (alignment + sizeof (void *))); + if (!p0) + return ((void *) 0); + p = PTR_ALIGN (p0, alignment, offset); + ORIG_PTR (p) = p0; + return p; +} + +void * +__mingw_aligned_malloc (size_t size, size_t alignment) +{ + return __mingw_aligned_offset_malloc (size, alignment, 0); +} + +void +__mingw_aligned_free (void *memblock) +{ + if (memblock) + free (ORIG_PTR (memblock)); +} + +void * +__mingw_aligned_offset_realloc (void *memblock, size_t size, + size_t alignment, size_t offset) +{ + void *p0, *p; + ptrdiff_t shift; + + if (!memblock) + return __mingw_aligned_offset_malloc (size, alignment, offset); + if (NOT_POWER_OF_TWO (alignment)) + goto bad; + if (size == 0) + { + __mingw_aligned_free (memblock); + return ((void *) 0); + } + if (alignment < sizeof (void *)) + alignment = sizeof (void *); + + p0 = ORIG_PTR (memblock); + /* It is an error for the alignment to change. */ + if (memblock != PTR_ALIGN (p0, alignment, offset)) + goto bad; + shift = CP (memblock) - CP (p0); + + p0 = realloc (p0, size + (alignment + sizeof (void *))); + if (!p0) + return ((void *) 0); + p = PTR_ALIGN (p0, alignment, offset); + + /* Relative shift of actual data may be different from before, ugh. */ + if (shift != CP (p) - CP (p0)) + /* ugh, moves more than necessary if size is increased. */ + memmove (CP (p), CP (p0) + shift, size); + + ORIG_PTR (p) = p0; + return p; + +bad: + errno = EINVAL; + return ((void *) 0); +} + +void * +__mingw_aligned_realloc (void *memblock, size_t size, size_t alignment) +{ + return __mingw_aligned_offset_realloc (memblock, size, alignment, 0); +} |