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