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)6void *__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