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