瀏覽代碼

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 年之前
父節點
當前提交
6d861ac874
共有 3 個文件被更改,包括 55 次插入49 次删除
  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;