master
 1#define _GNU_SOURCE
 2#include <stdlib.h>
 3#include <sys/mman.h>
 4#include <string.h>
 5#include "meta.h"
 6
 7void *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}