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