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

     1  #include <stdlib.h>
     2  #include <errno.h>
     3  #include "meta.h"
     4  
     5  void *aligned_alloc(size_t align, size_t len)
     6  {
     7  	if ((align & -align) != align) {
     8  		errno = EINVAL;
     9  		return 0;
    10  	}
    11  
    12  	if (len > SIZE_MAX - align || align >= (1ULL<<31)*UNIT) {
    13  		errno = ENOMEM;
    14  		return 0;
    15  	}
    16  
    17  	if (DISABLE_ALIGNED_ALLOC) {
    18  		errno = ENOMEM;
    19  		return 0;
    20  	}
    21  
    22  	if (align <= UNIT) align = UNIT;
    23  
    24  	unsigned char *p = malloc(len + align - UNIT);
    25  	struct meta *g = get_meta(p);
    26  	int idx = get_slot_index(p);
    27  	size_t stride = get_stride(g);
    28  	unsigned char *start = g->mem->storage + stride*idx;
    29  	unsigned char *end = g->mem->storage + stride*(idx+1) - IB;
    30  	size_t adj = -(uintptr_t)p & (align-1);
    31  
    32  	if (!adj) {
    33  		set_size(p, end, len);
    34  		return p;
    35  	}
    36  	p += adj;
    37  	uint32_t offset = (size_t)(p-g->mem->storage)/UNIT;
    38  	if (offset <= 0xffff) {
    39  		*(uint16_t *)(p-2) = offset;
    40  		p[-4] = 0;
    41  	} else {
    42  		// use a 32-bit offset if 16-bit doesn't fit. for this,
    43  		// 16-bit field must be zero, [-4] byte nonzero.
    44  		*(uint16_t *)(p-2) = 0;
    45  		*(uint32_t *)(p-8) = offset;
    46  		p[-4] = 1;
    47  	}
    48  	p[-3] = idx;
    49  	set_size(p, end, len);
    50  	// store offset to aligned enframing. this facilitates cycling
    51  	// offset and also iteration of heap for debugging/measurement.
    52  	// for extreme overalignment it won't fit but these are classless
    53  	// allocations anyway.
    54  	*(uint16_t *)(start - 2) = (size_t)(p-start)/UNIT;
    55  	start[-3] = 7<<5;
    56  	return p;
    57  }