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