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 <stdlib.h> |
||||
#include <stdint.h> |
|
||||
#include <errno.h> |
|
||||
|
|
||||
/* This function should work with most dlmalloc-like chunk bookkeeping
|
void *__memalign(size_t, size_t); |
||||
* systems, but it's only guaranteed to work with the native implementation |
|
||||
* used in this library. */ |
|
||||
|
|
||||
void *aligned_alloc(size_t align, size_t len) |
void *aligned_alloc(size_t align, size_t len) |
||||
{ |
{ |
||||
unsigned char *mem, *new, *end; |
return __memalign(align, len); |
||||
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; |
|
||||
} |
} |
||||
|
|||||
@ -1,7 +1,55 @@ |
|||||
#include <stdlib.h> |
#include <stdlib.h> |
||||
|
#include <stdint.h> |
||||
#include <errno.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