Browse Source

move core memalign code from aligned_alloc to __memalign

there are two motivations for this change. one is to avoid
gratuitously depending on a C11 symbol for implementing a POSIX
function. the other pertains to the documented semantics. C11 does not
define any behavior for aligned_alloc when the length argument is not
a multiple of the alignment argument. posix_memalign on the other hand
places no requirements on the length argument. using __memalign as the
implementation of both, rather than trying to implement one in terms
of the other when their documented contracts differ, eliminates this
confusion.
Rich Felker 11 years ago
parent
commit
6d861ac874
3 changed files with 55 additions and 49 deletions
  1. 2 46
      src/malloc/aligned_alloc.c
  2. 50 2
      src/malloc/memalign.c
  3. 3 1
      src/malloc/posix_memalign.c

+ 2 - 46
src/malloc/aligned_alloc.c

@@ -1,52 +1,8 @@
 #include <stdlib.h>
-#include <stdint.h>
-#include <errno.h>
 
-/* This function should work with most dlmalloc-like chunk bookkeeping
- * systems, but it's only guaranteed to work with the native implementation
- * used in this library. */
+void *__memalign(size_t, size_t);
 
 void *aligned_alloc(size_t align, size_t len)
 {
-	unsigned char *mem, *new, *end;
-	size_t header, footer;
-
-	if ((align & -align) != align) {
-		errno = EINVAL;
-		return NULL;
-	}
-
-	if (len > SIZE_MAX - align) {
-		errno = ENOMEM;
-		return NULL;
-	}
-
-	if (align <= 4*sizeof(size_t)) {
-		if (!(mem = malloc(len)))
-			return NULL;
-		return mem;
-	}
-
-	if (!(mem = malloc(len + align-1)))
-		return NULL;
-
-	header = ((size_t *)mem)[-1];
-	new = (void *)((uintptr_t)mem + align-1 & -align);
-
-	if (!(header & 7)) {
-		((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem);
-		((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem);
-		return new;
-	}
-
-	end = mem + (header & -8);
-	footer = ((size_t *)end)[-2];
-
-	((size_t *)mem)[-1] = header&7 | new-mem;
-	((size_t *)new)[-2] = footer&7 | new-mem;
-	((size_t *)new)[-1] = header&7 | end-new;
-	((size_t *)end)[-2] = footer&7 | end-new;
-
-	if (new != mem) free(mem);
-	return new;
+	return __memalign(align, len);
 }

+ 50 - 2
src/malloc/memalign.c

@@ -1,7 +1,55 @@
 #include <stdlib.h>
+#include <stdint.h>
 #include <errno.h>
+#include "libc.h"
 
-void *memalign(size_t align, size_t len)
+/* This function should work with most dlmalloc-like chunk bookkeeping
+ * systems, but it's only guaranteed to work with the native implementation
+ * used in this library. */
+
+void *__memalign(size_t align, size_t len)
 {
-	return aligned_alloc(align, len);
+	unsigned char *mem, *new, *end;
+	size_t header, footer;
+
+	if ((align & -align) != align) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (len > SIZE_MAX - align) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	if (align <= 4*sizeof(size_t)) {
+		if (!(mem = malloc(len)))
+			return NULL;
+		return mem;
+	}
+
+	if (!(mem = malloc(len + align-1)))
+		return NULL;
+
+	header = ((size_t *)mem)[-1];
+	new = (void *)((uintptr_t)mem + align-1 & -align);
+
+	if (!(header & 7)) {
+		((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem);
+		((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem);
+		return new;
+	}
+
+	end = mem + (header & -8);
+	footer = ((size_t *)end)[-2];
+
+	((size_t *)mem)[-1] = header&7 | new-mem;
+	((size_t *)new)[-2] = footer&7 | new-mem;
+	((size_t *)new)[-1] = header&7 | end-new;
+	((size_t *)end)[-2] = footer&7 | end-new;
+
+	if (new != mem) free(mem);
+	return new;
 }
+
+weak_alias(__memalign, memalign);

+ 3 - 1
src/malloc/posix_memalign.c

@@ -1,10 +1,12 @@
 #include <stdlib.h>
 #include <errno.h>
 
+void *__memalign(size_t, size_t);
+
 int posix_memalign(void **res, size_t align, size_t len)
 {
 	if (align < sizeof(void *)) return EINVAL;
-	void *mem = aligned_alloc(align, len);
+	void *mem = __memalign(align, len);
 	if (!mem) return errno;
 	*res = mem;
 	return 0;