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 
aligned_alloc(size_t align, size_t len)9 void *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