mirror of
https://github.com/ziglang/zig.git
synced 2026-01-13 10:55:11 +00:00
54 lines
1.3 KiB
C
Vendored
54 lines
1.3 KiB
C
Vendored
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
#include "malloc_impl.h"
|
|
|
|
void *aligned_alloc(size_t align, size_t len)
|
|
{
|
|
unsigned char *mem, *new;
|
|
|
|
if ((align & -align) != align) {
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
if (len > SIZE_MAX - align ||
|
|
(__malloc_replaced && !__aligned_alloc_replaced)) {
|
|
errno = ENOMEM;
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|