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