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

     1  #define _GNU_SOURCE
     2  #include <stdlib.h>
     3  #include <sys/mman.h>
     4  #include <string.h>
     5  #include "meta.h"
     6  
     7  void *realloc(void *p, size_t n)
     8  {
     9  	if (!p) return malloc(n);
    10  	if (size_overflows(n)) return 0;
    11  
    12  	struct meta *g = get_meta(p);
    13  	int idx = get_slot_index(p);
    14  	size_t stride = get_stride(g);
    15  	unsigned char *start = g->mem->storage + stride*idx;
    16  	unsigned char *end = start + stride - IB;
    17  	size_t old_size = get_nominal_size(p, end);
    18  	size_t avail_size = end-(unsigned char *)p;
    19  	void *new;
    20  
    21  	// only resize in-place if size class matches
    22  	if (n <= avail_size && n<MMAP_THRESHOLD
    23  	    && size_to_class(n)+1 >= g->sizeclass) {
    24  		set_size(p, end, n);
    25  		return p;
    26  	}
    27  
    28  	// use mremap if old and new size are both mmap-worthy
    29  	if (g->sizeclass>=48 && n>=MMAP_THRESHOLD) {
    30  		assert(g->sizeclass==63);
    31  		size_t base = (unsigned char *)p-start;
    32  		size_t needed = (n + base + UNIT + IB + 4095) & -4096;
    33  		new = g->maplen*4096UL == needed ? g->mem :
    34  			mremap(g->mem, g->maplen*4096UL, needed, MREMAP_MAYMOVE);
    35  		if (new!=MAP_FAILED) {
    36  			g->mem = new;
    37  			g->maplen = needed/4096;
    38  			p = g->mem->storage + base;
    39  			end = g->mem->storage + (needed - UNIT) - IB;
    40  			*end = 0;
    41  			set_size(p, end, n);
    42  			return p;
    43  		}
    44  	}
    45  
    46  	new = malloc(n);
    47  	if (!new) return 0;
    48  	memcpy(new, p, n < old_size ? n : old_size);
    49  	free(p);
    50  	return new;
    51  }