X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fmalloc%2Fmemalign.c;h=cf9dfbda66ca295c543a16ff1202ef0a118f785b;hb=03919b26ed41c31876db41f7cee076ced4513fad;hp=61f456e48667e6a717802eadc5a471d46a8121a7;hpb=0b44a0315b47dd8eced9f3b7f31580cf14bbfc01;p=musl diff --git a/src/malloc/memalign.c b/src/malloc/memalign.c index 61f456e4..cf9dfbda 100644 --- a/src/malloc/memalign.c +++ b/src/malloc/memalign.c @@ -1,13 +1,54 @@ #include +#include #include +#include "malloc_impl.h" -void *memalign(size_t align, size_t len) +void *__memalign(size_t align, size_t len) { - void *mem; - int ret; - if ((ret = posix_memalign(&mem, align, len))) { - errno = ret; + unsigned char *mem, *new; + + if ((align & -align) != align) { + errno = EINVAL; + return 0; + } + + if (len > SIZE_MAX - align || __malloc_replaced) { + errno = ENOMEM; return 0; } - return mem; + + if (align <= SIZE_ALIGN) + return malloc(len); + + if (!(mem = malloc(len + align-1))) + return 0; + + new = (void *)((uintptr_t)mem + align-1 & -align); + if (new == mem) return mem; + + struct chunk *c = MEM_TO_CHUNK(mem); + struct chunk *n = MEM_TO_CHUNK(new); + + if (IS_MMAPPED(c)) { + /* Apply difference between aligned and original + * address to the "extra" field of mmapped chunk. */ + n->psize = c->psize + (new-mem); + n->csize = c->csize - (new-mem); + return new; + } + + struct chunk *t = NEXT_CHUNK(c); + + /* Split the allocated chunk into two chunks. The aligned part + * that will be used has the size in its footer reduced by the + * difference between the aligned and original addresses, and + * the resulting size copied to its header. A new header and + * footer are written for the split-off part to be freed. */ + n->psize = c->csize = C_INUSE | (new-mem); + n->csize = t->psize -= new-mem; + + __bin_chunk(c); + return new; } + +weak_alias(__memalign, memalign);