1#include <stdlib.h>
2#include <stdint.h>
3#include <errno.h>
4#include "malloc_impl.h"
5#ifdef __LITEOS_A__
6#include "dynlink.h"
7#endif
8
9void *aligned_alloc(size_t align, size_t len)
10{
11	unsigned char *mem, *new;
12
13	if ((align & -align) != align) {
14		errno = EINVAL;
15		return 0;
16	}
17
18	if (len > SIZE_MAX - align ||
19	    (__malloc_replaced && !__aligned_alloc_replaced)) {
20		errno = ENOMEM;
21		return 0;
22	}
23
24	if (align <= SIZE_ALIGN)
25		return malloc(len);
26
27	if (!(mem = malloc(len + align-1)))
28		return 0;
29
30	new = (void *)((uintptr_t)mem + align-1 & -align);
31	if (new == mem) return mem;
32
33	struct chunk *c = MEM_TO_CHUNK(mem);
34	struct chunk *n = MEM_TO_CHUNK(new);
35
36	if (IS_MMAPPED(c)) {
37		/* Apply difference between aligned and original
38		 * address to the "extra" field of mmapped chunk. */
39		n->psize = c->psize + (new-mem);
40		n->csize = c->csize - (new-mem);
41		return new;
42	}
43
44	struct chunk *t = NEXT_CHUNK(c);
45
46	/* Split the allocated chunk into two chunks. The aligned part
47	 * that will be used has the size in its footer reduced by the
48	 * difference between the aligned and original addresses, and
49	 * the resulting size copied to its header. A new header and
50	 * footer are written for the split-off part to be freed. */
51	n->psize = c->csize = C_INUSE | (new-mem);
52	n->csize = t->psize -= new-mem;
53
54	__bin_chunk(c);
55	return new;
56}
57