realloc.c raw

   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  }
  52