github.com/afumu/libc@v0.0.6/musl/src/malloc/oldmalloc/aligned_alloc.c (about)

     1  #include <stdlib.h>
     2  #include <stdint.h>
     3  #include <errno.h>
     4  #include "malloc_impl.h"
     5  
     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  }