1570af302Sopenharmony_ci#include <stdlib.h>
2570af302Sopenharmony_ci#include <stdint.h>
3570af302Sopenharmony_ci#include <errno.h>
4570af302Sopenharmony_ci#include "malloc_impl.h"
5570af302Sopenharmony_ci#ifdef __LITEOS_A__
6570af302Sopenharmony_ci#include "dynlink.h"
7570af302Sopenharmony_ci#endif
8570af302Sopenharmony_ci
9570af302Sopenharmony_civoid *aligned_alloc(size_t align, size_t len)
10570af302Sopenharmony_ci{
11570af302Sopenharmony_ci	unsigned char *mem, *new;
12570af302Sopenharmony_ci
13570af302Sopenharmony_ci	if ((align & -align) != align) {
14570af302Sopenharmony_ci		errno = EINVAL;
15570af302Sopenharmony_ci		return 0;
16570af302Sopenharmony_ci	}
17570af302Sopenharmony_ci
18570af302Sopenharmony_ci	if (len > SIZE_MAX - align ||
19570af302Sopenharmony_ci	    (__malloc_replaced && !__aligned_alloc_replaced)) {
20570af302Sopenharmony_ci		errno = ENOMEM;
21570af302Sopenharmony_ci		return 0;
22570af302Sopenharmony_ci	}
23570af302Sopenharmony_ci
24570af302Sopenharmony_ci	if (align <= SIZE_ALIGN)
25570af302Sopenharmony_ci		return malloc(len);
26570af302Sopenharmony_ci
27570af302Sopenharmony_ci	if (!(mem = malloc(len + align-1)))
28570af302Sopenharmony_ci		return 0;
29570af302Sopenharmony_ci
30570af302Sopenharmony_ci	new = (void *)((uintptr_t)mem + align-1 & -align);
31570af302Sopenharmony_ci	if (new == mem) return mem;
32570af302Sopenharmony_ci
33570af302Sopenharmony_ci	struct chunk *c = MEM_TO_CHUNK(mem);
34570af302Sopenharmony_ci	struct chunk *n = MEM_TO_CHUNK(new);
35570af302Sopenharmony_ci
36570af302Sopenharmony_ci	if (IS_MMAPPED(c)) {
37570af302Sopenharmony_ci		/* Apply difference between aligned and original
38570af302Sopenharmony_ci		 * address to the "extra" field of mmapped chunk. */
39570af302Sopenharmony_ci		n->psize = c->psize + (new-mem);
40570af302Sopenharmony_ci		n->csize = c->csize - (new-mem);
41570af302Sopenharmony_ci		return new;
42570af302Sopenharmony_ci	}
43570af302Sopenharmony_ci
44570af302Sopenharmony_ci	struct chunk *t = NEXT_CHUNK(c);
45570af302Sopenharmony_ci
46570af302Sopenharmony_ci	/* Split the allocated chunk into two chunks. The aligned part
47570af302Sopenharmony_ci	 * that will be used has the size in its footer reduced by the
48570af302Sopenharmony_ci	 * difference between the aligned and original addresses, and
49570af302Sopenharmony_ci	 * the resulting size copied to its header. A new header and
50570af302Sopenharmony_ci	 * footer are written for the split-off part to be freed. */
51570af302Sopenharmony_ci	n->psize = c->csize = C_INUSE | (new-mem);
52570af302Sopenharmony_ci	n->csize = t->psize -= new-mem;
53570af302Sopenharmony_ci
54570af302Sopenharmony_ci	__bin_chunk(c);
55570af302Sopenharmony_ci	return new;
56570af302Sopenharmony_ci}
57