diff options
| author | Rich Felker <dalias@aerifal.cx> | 2013-07-04 23:58:16 -0400 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2013-07-04 23:58:16 -0400 | 
| commit | 6d861ac87491a207e4599c44b61d142f0a601c2d (patch) | |
| tree | 2458b79e37b144f13fb5190a7bcf777d1b9b883a | |
| parent | 651416182dc65d75e91cadfec65dd72f9ff07846 (diff) | |
| download | musl-6d861ac87491a207e4599c44b61d142f0a601c2d.tar.gz | |
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.
| -rw-r--r-- | src/malloc/aligned_alloc.c | 48 | ||||
| -rw-r--r-- | src/malloc/memalign.c | 52 | ||||
| -rw-r--r-- | src/malloc/posix_memalign.c | 4 | 
3 files changed, 55 insertions, 49 deletions
| diff --git a/src/malloc/aligned_alloc.c b/src/malloc/aligned_alloc.c index c6386629..cc0a8012 100644 --- a/src/malloc/aligned_alloc.c +++ b/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);  } diff --git a/src/malloc/memalign.c b/src/malloc/memalign.c index a594c636..55fe68e8 100644 --- a/src/malloc/memalign.c +++ b/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); diff --git a/src/malloc/posix_memalign.c b/src/malloc/posix_memalign.c index ad4d8f47..cf67db63 100644 --- a/src/malloc/posix_memalign.c +++ b/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; | 
