mirror of https://git.musl-libc.org/git/musl
Browse Source
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.rs-1.0
3 changed files with 55 additions and 49 deletions
@ -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); |
|||
} |
|||
|
|||
@ -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); |
|||
|
|||
Loading…
Reference in new issue