summaryrefslogtreecommitdiffstats
path: root/winsup/mingw/mingwex/mingw-aligned-malloc.c
diff options
context:
space:
mode:
authorDanny Smith <dannysmith@users.sourceforge.net>2004-08-24 08:55:42 +0000
committerDanny Smith <dannysmith@users.sourceforge.net>2004-08-24 08:55:42 +0000
commita6c2ea7e7c363f691fc4dc683c0772b3dab2db70 (patch)
tree2dcf0f2de94d02565181d94366cab207d200fa37 /winsup/mingw/mingwex/mingw-aligned-malloc.c
parent45b1139e413d3939436dac636991a5bbbfd7e9ad (diff)
downloadcygnal-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-xwinsup/mingw/mingwex/mingw-aligned-malloc.c120
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);
+}