mirror of
https://github.com/fluencelabs/musl
synced 2025-04-25 15:22:15 +00:00
using malloc implementation types/macros/idioms for memalign
the generated code should be mostly unchanged, except for explicit use of C_INUSE in place of copying the low bits from existing chunk headers/footers. these changes also remove mild UB due to dubious arithmetic on pointers into imaginary size_t[] arrays.
This commit is contained in:
parent
23389b1988
commit
3c2cbbe7ba
@ -2,49 +2,51 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
|
#include "malloc_impl.h"
|
||||||
|
|
||||||
void *__memalign(size_t align, size_t len)
|
void *__memalign(size_t align, size_t len)
|
||||||
{
|
{
|
||||||
unsigned char *mem, *new, *end;
|
unsigned char *mem, *new;
|
||||||
size_t header, footer;
|
|
||||||
|
|
||||||
if ((align & -align) != align) {
|
if ((align & -align) != align) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > SIZE_MAX - align) {
|
if (len > SIZE_MAX - align) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (align <= 4*sizeof(size_t)) {
|
if (align <= SIZE_ALIGN)
|
||||||
if (!(mem = malloc(len)))
|
return malloc(len);
|
||||||
return NULL;
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(mem = malloc(len + align-1)))
|
if (!(mem = malloc(len + align-1)))
|
||||||
return NULL;
|
return 0;
|
||||||
|
|
||||||
new = (void *)((uintptr_t)mem + align-1 & -align);
|
new = (void *)((uintptr_t)mem + align-1 & -align);
|
||||||
if (new == mem) return mem;
|
if (new == mem) return mem;
|
||||||
|
|
||||||
header = ((size_t *)mem)[-1];
|
struct chunk *c = MEM_TO_CHUNK(mem);
|
||||||
|
struct chunk *n = MEM_TO_CHUNK(new);
|
||||||
|
|
||||||
if (!(header & 7)) {
|
if (IS_MMAPPED(c)) {
|
||||||
((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem);
|
/* Apply difference between aligned and original
|
||||||
((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem);
|
* address to the "extra" field of mmapped chunk. */
|
||||||
|
n->psize = c->psize + (new-mem);
|
||||||
|
n->csize = c->csize - (new-mem);
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = mem + (header & -8);
|
struct chunk *t = NEXT_CHUNK(c);
|
||||||
footer = ((size_t *)end)[-2];
|
|
||||||
|
|
||||||
((size_t *)mem)[-1] = header&7 | new-mem;
|
/* Split the allocated chunk into two chunks. The aligned part
|
||||||
((size_t *)new)[-2] = footer&7 | new-mem;
|
* that will be used has the size in its footer reduced by the
|
||||||
((size_t *)new)[-1] = header&7 | end-new;
|
* difference between the aligned and original addresses, and
|
||||||
((size_t *)end)[-2] = footer&7 | end-new;
|
* 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;
|
||||||
|
|
||||||
free(mem);
|
free(mem);
|
||||||
return new;
|
return new;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user