xref: /plan9/sys/src/9/port/debugalloc.c (revision 72061b92c86a7d2b16e3ab31edd3846f53c84345)
19a747e4fSDavid du Colombier #include	"u.h"
29a747e4fSDavid du Colombier #include	"../port/lib.h"
39a747e4fSDavid du Colombier #include	"mem.h"
49a747e4fSDavid du Colombier #include	"pool.h"
59a747e4fSDavid du Colombier #include	"dat.h"
69a747e4fSDavid du Colombier #include	"fns.h"
79a747e4fSDavid du Colombier #include	"error.h"
89a747e4fSDavid du Colombier 
99a747e4fSDavid du Colombier #define left	u.s.bhl
109a747e4fSDavid du Colombier #define right	u.s.bhr
119a747e4fSDavid du Colombier #define fwd	u.s.bhf
129a747e4fSDavid du Colombier #define prev	u.s.bhv
139a747e4fSDavid du Colombier #define parent	u.s.bhp
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier typedef struct Bhdr	Bhdr;
169a747e4fSDavid du Colombier 
179a747e4fSDavid du Colombier struct Bhdr {
189a747e4fSDavid du Colombier 	ulong	magic;
199a747e4fSDavid du Colombier 	ulong	size;
209a747e4fSDavid du Colombier };
219a747e4fSDavid du Colombier enum {
229a747e4fSDavid du Colombier 	NOT_MAGIC = 0xdeadfa11,
239a747e4fSDavid du Colombier };
249a747e4fSDavid du Colombier 
259a747e4fSDavid du Colombier struct Pool
269a747e4fSDavid du Colombier {
279a747e4fSDavid du Colombier 	char*	name;
289a747e4fSDavid du Colombier 	ulong	maxsize;
299a747e4fSDavid du Colombier 	int	quanta;
309a747e4fSDavid du Colombier 	int	chunk;
319a747e4fSDavid du Colombier 	ulong	cursize;
329a747e4fSDavid du Colombier 	ulong	arenasize;
339a747e4fSDavid du Colombier 	ulong	hw;
349a747e4fSDavid du Colombier 	Lock	l;
359a747e4fSDavid du Colombier 	Bhdr*	root;
369a747e4fSDavid du Colombier 	Bhdr*	chain;
379a747e4fSDavid du Colombier 	int	nalloc;
389a747e4fSDavid du Colombier 	int	nfree;
399a747e4fSDavid du Colombier 	int	nbrk;
409a747e4fSDavid du Colombier 	int	lastfree;
419a747e4fSDavid du Colombier 	void	(*move)(void*, void*);
429a747e4fSDavid du Colombier };
439a747e4fSDavid du Colombier 
449a747e4fSDavid du Colombier struct
459a747e4fSDavid du Colombier {
469a747e4fSDavid du Colombier 	int	n;
479a747e4fSDavid du Colombier 	Pool	pool[MAXPOOL];
489a747e4fSDavid du Colombier 	Lock	l;
499a747e4fSDavid du Colombier } table = {
509a747e4fSDavid du Colombier 	2,
519a747e4fSDavid du Colombier 	{
529a747e4fSDavid du Colombier 		{ "Main",	 4*1024*1024, 31,  128*1024 },
539a747e4fSDavid du Colombier 		{ "Image",	 16*1024*1024, 31, 2*1024*1024 },
549a747e4fSDavid du Colombier 	}
559a747e4fSDavid du Colombier };
569a747e4fSDavid du Colombier 
579a747e4fSDavid du Colombier Pool*	mainmem = &table.pool[0];
589a747e4fSDavid du Colombier Pool*	imagmem = &table.pool[1];
599a747e4fSDavid du Colombier 
609a747e4fSDavid du Colombier int	poolcompact(Pool*);
619a747e4fSDavid du Colombier 
629a747e4fSDavid du Colombier Bhdr*
poolchain(Pool * p)639a747e4fSDavid du Colombier poolchain(Pool *p)
649a747e4fSDavid du Colombier {
659a747e4fSDavid du Colombier 	return p->chain;
669a747e4fSDavid du Colombier }
679a747e4fSDavid du Colombier 
689a747e4fSDavid du Colombier void
pooldel(Pool * p,Bhdr * t)699a747e4fSDavid du Colombier pooldel(Pool *p, Bhdr *t)
709a747e4fSDavid du Colombier {
719a747e4fSDavid du Colombier 	Bhdr *s, *f, *rp, *q;
729a747e4fSDavid du Colombier 
739a747e4fSDavid du Colombier 	if(t->parent == nil && p->root != t) {
749a747e4fSDavid du Colombier 		t->prev->fwd = t->fwd;
759a747e4fSDavid du Colombier 		t->fwd->prev = t->prev;
769a747e4fSDavid du Colombier 		return;
779a747e4fSDavid du Colombier 	}
789a747e4fSDavid du Colombier 
799a747e4fSDavid du Colombier 	if(t->fwd != t) {
809a747e4fSDavid du Colombier 		f = t->fwd;
819a747e4fSDavid du Colombier 		s = t->parent;
829a747e4fSDavid du Colombier 		f->parent = s;
839a747e4fSDavid du Colombier 		if(s == nil)
849a747e4fSDavid du Colombier 			p->root = f;
859a747e4fSDavid du Colombier 		else {
869a747e4fSDavid du Colombier 			if(s->left == t)
879a747e4fSDavid du Colombier 				s->left = f;
889a747e4fSDavid du Colombier 			else
899a747e4fSDavid du Colombier 				s->right = f;
909a747e4fSDavid du Colombier 		}
919a747e4fSDavid du Colombier 
929a747e4fSDavid du Colombier 		rp = t->left;
939a747e4fSDavid du Colombier 		f->left = rp;
949a747e4fSDavid du Colombier 		if(rp != nil)
959a747e4fSDavid du Colombier 			rp->parent = f;
969a747e4fSDavid du Colombier 		rp = t->right;
979a747e4fSDavid du Colombier 		f->right = rp;
989a747e4fSDavid du Colombier 		if(rp != nil)
999a747e4fSDavid du Colombier 			rp->parent = f;
1009a747e4fSDavid du Colombier 
1019a747e4fSDavid du Colombier 		t->prev->fwd = t->fwd;
1029a747e4fSDavid du Colombier 		t->fwd->prev = t->prev;
1039a747e4fSDavid du Colombier 		return;
1049a747e4fSDavid du Colombier 	}
1059a747e4fSDavid du Colombier 
1069a747e4fSDavid du Colombier 	if(t->left == nil)
1079a747e4fSDavid du Colombier 		rp = t->right;
1089a747e4fSDavid du Colombier 	else {
1099a747e4fSDavid du Colombier 		if(t->right == nil)
1109a747e4fSDavid du Colombier 			rp = t->left;
1119a747e4fSDavid du Colombier 		else {
1129a747e4fSDavid du Colombier 			f = t;
1139a747e4fSDavid du Colombier 			rp = t->right;
1149a747e4fSDavid du Colombier 			s = rp->left;
1159a747e4fSDavid du Colombier 			while(s != nil) {
1169a747e4fSDavid du Colombier 				f = rp;
1179a747e4fSDavid du Colombier 				rp = s;
1189a747e4fSDavid du Colombier 				s = rp->left;
1199a747e4fSDavid du Colombier 			}
1209a747e4fSDavid du Colombier 			if(f != t) {
1219a747e4fSDavid du Colombier 				s = rp->right;
1229a747e4fSDavid du Colombier 				f->left = s;
1239a747e4fSDavid du Colombier 				if(s != nil)
1249a747e4fSDavid du Colombier 					s->parent = f;
1259a747e4fSDavid du Colombier 				s = t->right;
1269a747e4fSDavid du Colombier 				rp->right = s;
1279a747e4fSDavid du Colombier 				if(s != nil)
1289a747e4fSDavid du Colombier 					s->parent = rp;
1299a747e4fSDavid du Colombier 			}
1309a747e4fSDavid du Colombier 			s = t->left;
1319a747e4fSDavid du Colombier 			rp->left = s;
1329a747e4fSDavid du Colombier 			s->parent = rp;
1339a747e4fSDavid du Colombier 		}
1349a747e4fSDavid du Colombier 	}
1359a747e4fSDavid du Colombier 	q = t->parent;
1369a747e4fSDavid du Colombier 	if(q == nil)
1379a747e4fSDavid du Colombier 		p->root = rp;
1389a747e4fSDavid du Colombier 	else {
1399a747e4fSDavid du Colombier 		if(t == q->left)
1409a747e4fSDavid du Colombier 			q->left = rp;
1419a747e4fSDavid du Colombier 		else
1429a747e4fSDavid du Colombier 			q->right = rp;
1439a747e4fSDavid du Colombier 	}
1449a747e4fSDavid du Colombier 	if(rp != nil)
1459a747e4fSDavid du Colombier 		rp->parent = q;
1469a747e4fSDavid du Colombier }
1479a747e4fSDavid du Colombier 
1489a747e4fSDavid du Colombier void
pooladd(Pool * p,Bhdr * q)1499a747e4fSDavid du Colombier pooladd(Pool *p, Bhdr *q)
1509a747e4fSDavid du Colombier {
1519a747e4fSDavid du Colombier 	int size;
1529a747e4fSDavid du Colombier 	Bhdr *tp, *t;
1539a747e4fSDavid du Colombier 
1549a747e4fSDavid du Colombier 	q->magic = MAGIC_F;
1559a747e4fSDavid du Colombier 
1569a747e4fSDavid du Colombier 	q->left = nil;
1579a747e4fSDavid du Colombier 	q->right = nil;
1589a747e4fSDavid du Colombier 	q->parent = nil;
1599a747e4fSDavid du Colombier 	q->fwd = q;
1609a747e4fSDavid du Colombier 	q->prev = q;
1619a747e4fSDavid du Colombier 
1629a747e4fSDavid du Colombier 	t = p->root;
1639a747e4fSDavid du Colombier 	if(t == nil) {
1649a747e4fSDavid du Colombier 		p->root = q;
1659a747e4fSDavid du Colombier 		return;
1669a747e4fSDavid du Colombier 	}
1679a747e4fSDavid du Colombier 
1689a747e4fSDavid du Colombier 	size = q->size;
1699a747e4fSDavid du Colombier 
1709a747e4fSDavid du Colombier 	tp = nil;
1719a747e4fSDavid du Colombier 	while(t != nil) {
1729a747e4fSDavid du Colombier 		if(size == t->size) {
1739a747e4fSDavid du Colombier 			q->fwd = t->fwd;
1749a747e4fSDavid du Colombier 			q->fwd->prev = q;
1759a747e4fSDavid du Colombier 			q->prev = t;
1769a747e4fSDavid du Colombier 			t->fwd = q;
1779a747e4fSDavid du Colombier 			return;
1789a747e4fSDavid du Colombier 		}
1799a747e4fSDavid du Colombier 		tp = t;
1809a747e4fSDavid du Colombier 		if(size < t->size)
1819a747e4fSDavid du Colombier 			t = t->left;
1829a747e4fSDavid du Colombier 		else
1839a747e4fSDavid du Colombier 			t = t->right;
1849a747e4fSDavid du Colombier 	}
1859a747e4fSDavid du Colombier 
1869a747e4fSDavid du Colombier 	q->parent = tp;
1879a747e4fSDavid du Colombier 	if(size < tp->size)
1889a747e4fSDavid du Colombier 		tp->left = q;
1899a747e4fSDavid du Colombier 	else
1909a747e4fSDavid du Colombier 		tp->right = q;
1919a747e4fSDavid du Colombier }
1929a747e4fSDavid du Colombier 
1939a747e4fSDavid du Colombier void*
poolalloc(Pool * p,int size)1949a747e4fSDavid du Colombier poolalloc(Pool *p, int size)
1959a747e4fSDavid du Colombier {
1969a747e4fSDavid du Colombier 	Bhdr *q, *t;
1979a747e4fSDavid du Colombier 	int alloc, ldr, ns, frag;
1989a747e4fSDavid du Colombier 
1999a747e4fSDavid du Colombier 	if(size < 0 || size >= 1024*1024*1024)	/* for sanity and to avoid overflow */
2009a747e4fSDavid du Colombier 		return nil;
2019a747e4fSDavid du Colombier 	size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
2029a747e4fSDavid du Colombier 
2039a747e4fSDavid du Colombier 	ilock(&p->l);
2049a747e4fSDavid du Colombier 	p->nalloc++;
2059a747e4fSDavid du Colombier 
2069a747e4fSDavid du Colombier 	t = p->root;
2079a747e4fSDavid du Colombier 	q = nil;
2089a747e4fSDavid du Colombier 	while(t) {
2099a747e4fSDavid du Colombier 		if(t->size == size) {
2109a747e4fSDavid du Colombier 			pooldel(p, t);
2119a747e4fSDavid du Colombier 			t->magic = MAGIC_A;
2129a747e4fSDavid du Colombier 			p->cursize += t->size;
2139a747e4fSDavid du Colombier 			if(p->cursize > p->hw)
2149a747e4fSDavid du Colombier 				p->hw = p->cursize;
2159a747e4fSDavid du Colombier 			iunlock(&p->l);
2169a747e4fSDavid du Colombier 			return B2D(t);
2179a747e4fSDavid du Colombier 		}
2189a747e4fSDavid du Colombier 		if(size < t->size) {
2199a747e4fSDavid du Colombier 			q = t;
2209a747e4fSDavid du Colombier 			t = t->left;
2219a747e4fSDavid du Colombier 		}
2229a747e4fSDavid du Colombier 		else
2239a747e4fSDavid du Colombier 			t = t->right;
2249a747e4fSDavid du Colombier 	}
2259a747e4fSDavid du Colombier 	if(q != nil) {
2269a747e4fSDavid du Colombier 		pooldel(p, q);
2279a747e4fSDavid du Colombier 		q->magic = MAGIC_A;
2289a747e4fSDavid du Colombier 		frag = q->size - size;
2299a747e4fSDavid du Colombier 		if(frag < (size>>2)) {
2309a747e4fSDavid du Colombier 			p->cursize += q->size;
2319a747e4fSDavid du Colombier 			if(p->cursize > p->hw)
2329a747e4fSDavid du Colombier 				p->hw = p->cursize;
2339a747e4fSDavid du Colombier 			iunlock(&p->l);
2349a747e4fSDavid du Colombier 			return B2D(q);
2359a747e4fSDavid du Colombier 		}
2369a747e4fSDavid du Colombier 		/* Split */
2379a747e4fSDavid du Colombier 		ns = q->size - size;
2389a747e4fSDavid du Colombier 		q->size = size;
2399a747e4fSDavid du Colombier 		B2T(q)->hdr = q;
2409a747e4fSDavid du Colombier 		t = B2NB(q);
2419a747e4fSDavid du Colombier 		t->size = ns;
2429a747e4fSDavid du Colombier 		B2T(t)->hdr = t;
2439a747e4fSDavid du Colombier 		pooladd(p, t);
2449a747e4fSDavid du Colombier 		p->cursize += q->size;
2459a747e4fSDavid du Colombier 		if(p->cursize > p->hw)
2469a747e4fSDavid du Colombier 			p->hw = p->cursize;
2479a747e4fSDavid du Colombier 		iunlock(&p->l);
2489a747e4fSDavid du Colombier 		return B2D(q);
2499a747e4fSDavid du Colombier 	}
2509a747e4fSDavid du Colombier 
2519a747e4fSDavid du Colombier 	ns = p->chunk;
2529a747e4fSDavid du Colombier 	if(size > ns)
2539a747e4fSDavid du Colombier 		ns = size;
2549a747e4fSDavid du Colombier 	ldr = p->quanta+1;
2559a747e4fSDavid du Colombier 
2569a747e4fSDavid du Colombier 	alloc = ns+ldr+sizeof(t->magic);
2579a747e4fSDavid du Colombier 	p->arenasize += alloc;
2589a747e4fSDavid du Colombier 	if(p->arenasize > p->maxsize) {
2599a747e4fSDavid du Colombier 		p->arenasize -= alloc;
2609a747e4fSDavid du Colombier 
2619a747e4fSDavid du Colombier 		if(poolcompact(p)) {
2629a747e4fSDavid du Colombier 			iunlock(&p->l);
2639a747e4fSDavid du Colombier 			return poolalloc(p, size);
2649a747e4fSDavid du Colombier 		}
2659a747e4fSDavid du Colombier 
2669a747e4fSDavid du Colombier 		iunlock(&p->l);
2679a747e4fSDavid du Colombier 		print("%s arena too large: size %d cursize %lud arenasize %lud maxsize %lud\n",
2689a747e4fSDavid du Colombier 			 p->name, size, p->cursize, p->arenasize, p->maxsize);
2699a747e4fSDavid du Colombier 		return nil;
2709a747e4fSDavid du Colombier 	}
2719a747e4fSDavid du Colombier 
2729a747e4fSDavid du Colombier 	p->nbrk++;
2739a747e4fSDavid du Colombier 	t = xalloc(alloc);
2749a747e4fSDavid du Colombier 	if(t == nil) {
2759a747e4fSDavid du Colombier 		iunlock(&p->l);
2769a747e4fSDavid du Colombier 		return nil;
2779a747e4fSDavid du Colombier 	}
2789a747e4fSDavid du Colombier 
2799a747e4fSDavid du Colombier 	t->magic = MAGIC_E;		/* Make a leader */
2809a747e4fSDavid du Colombier 	t->size = ldr;
2819a747e4fSDavid du Colombier 	t->csize = ns+ldr;
2829a747e4fSDavid du Colombier 	t->clink = p->chain;
2839a747e4fSDavid du Colombier 	p->chain = t;
2849a747e4fSDavid du Colombier 	B2T(t)->hdr = t;
2859a747e4fSDavid du Colombier 	t = B2NB(t);
2869a747e4fSDavid du Colombier 
2879a747e4fSDavid du Colombier 	t->magic = MAGIC_A;		/* Make the block we are going to return */
2889a747e4fSDavid du Colombier 	t->size = size;
2899a747e4fSDavid du Colombier 	B2T(t)->hdr = t;
2909a747e4fSDavid du Colombier 	q = t;
2919a747e4fSDavid du Colombier 
2929a747e4fSDavid du Colombier 	ns -= size;			/* Free the rest */
2939a747e4fSDavid du Colombier 	if(ns > 0) {
2949a747e4fSDavid du Colombier 		q = B2NB(t);
2959a747e4fSDavid du Colombier 		q->size = ns;
2969a747e4fSDavid du Colombier 		B2T(q)->hdr = q;
2979a747e4fSDavid du Colombier 		pooladd(p, q);
2989a747e4fSDavid du Colombier 	}
2999a747e4fSDavid du Colombier 	B2NB(q)->magic = MAGIC_E;	/* Mark the end of the chunk */
3009a747e4fSDavid du Colombier 
3019a747e4fSDavid du Colombier 	p->cursize += t->size;
3029a747e4fSDavid du Colombier 	if(p->cursize > p->hw)
3039a747e4fSDavid du Colombier 		p->hw = p->cursize;
3049a747e4fSDavid du Colombier 	iunlock(&p->l);
3059a747e4fSDavid du Colombier 	return B2D(t);
3069a747e4fSDavid du Colombier }
3079a747e4fSDavid du Colombier 
3089a747e4fSDavid du Colombier void
poolfree(Pool * p,void * v)3099a747e4fSDavid du Colombier poolfree(Pool *p, void *v)
3109a747e4fSDavid du Colombier {
3119a747e4fSDavid du Colombier 	Bhdr *b, *c;
3129a747e4fSDavid du Colombier 
3139a747e4fSDavid du Colombier 	D2B(b, v);
3149a747e4fSDavid du Colombier 
3159a747e4fSDavid du Colombier 	ilock(&p->l);
3169a747e4fSDavid du Colombier 	p->nfree++;
3179a747e4fSDavid du Colombier 	p->cursize -= b->size;
3189a747e4fSDavid du Colombier 
3199a747e4fSDavid du Colombier 	c = B2NB(b);
3209a747e4fSDavid du Colombier 	if(c->magic == MAGIC_F) {	/* Join forward */
3219a747e4fSDavid du Colombier 		pooldel(p, c);
3229a747e4fSDavid du Colombier 		c->magic = 0;
3239a747e4fSDavid du Colombier 		b->size += c->size;
3249a747e4fSDavid du Colombier 		B2T(b)->hdr = b;
3259a747e4fSDavid du Colombier 	}
3269a747e4fSDavid du Colombier 
3279a747e4fSDavid du Colombier 	c = B2PT(b)->hdr;
3289a747e4fSDavid du Colombier 	if(c->magic == MAGIC_F) {	/* Join backward */
3299a747e4fSDavid du Colombier 		pooldel(p, c);
3309a747e4fSDavid du Colombier 		b->magic = 0;
3319a747e4fSDavid du Colombier 		c->size += b->size;
3329a747e4fSDavid du Colombier 		b = c;
3339a747e4fSDavid du Colombier 		B2T(b)->hdr = b;
3349a747e4fSDavid du Colombier 	}
3359a747e4fSDavid du Colombier 
3369a747e4fSDavid du Colombier 	pooladd(p, b);
3379a747e4fSDavid du Colombier 	iunlock(&p->l);
3389a747e4fSDavid du Colombier }
3399a747e4fSDavid du Colombier 
3409a747e4fSDavid du Colombier int
poolread(char * va,int count,ulong offset)3419a747e4fSDavid du Colombier poolread(char *va, int count, ulong offset)
3429a747e4fSDavid du Colombier {
3439a747e4fSDavid du Colombier 	Pool *p;
3449a747e4fSDavid du Colombier 	int n, i, signed_off;
3459a747e4fSDavid du Colombier 
3469a747e4fSDavid du Colombier 	n = 0;
3479a747e4fSDavid du Colombier 	signed_off = offset;
3489a747e4fSDavid du Colombier 	for(i = 0; i < table.n; i++) {
3499a747e4fSDavid du Colombier 		p = &table.pool[i];
3509a747e4fSDavid du Colombier 		n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n",
3519a747e4fSDavid du Colombier 			p->cursize,
3529a747e4fSDavid du Colombier 			p->maxsize,
3539a747e4fSDavid du Colombier 			p->hw,
3549a747e4fSDavid du Colombier 			p->nalloc,
3559a747e4fSDavid du Colombier 			p->nfree,
3569a747e4fSDavid du Colombier 			p->nbrk,
3579a747e4fSDavid du Colombier 			p->name);
3589a747e4fSDavid du Colombier 
3599a747e4fSDavid du Colombier 		if(signed_off > 0) {
3609a747e4fSDavid du Colombier 			signed_off -= n;
3619a747e4fSDavid du Colombier 			if(signed_off < 0) {
3629a747e4fSDavid du Colombier 				memmove(va, va+n+signed_off, -signed_off);
3639a747e4fSDavid du Colombier 				n = -signed_off;
3649a747e4fSDavid du Colombier 			}
3659a747e4fSDavid du Colombier 			else
3669a747e4fSDavid du Colombier 				n = 0;
3679a747e4fSDavid du Colombier 		}
3689a747e4fSDavid du Colombier 
3699a747e4fSDavid du Colombier 	}
3709a747e4fSDavid du Colombier 	return n;
3719a747e4fSDavid du Colombier }
3729a747e4fSDavid du Colombier 
3739a747e4fSDavid du Colombier Lock pcxlock;
3749a747e4fSDavid du Colombier struct {
3759a747e4fSDavid du Colombier 	ulong	n;
3769a747e4fSDavid du Colombier 	ulong	pc;
3779a747e4fSDavid du Colombier } pcx[1024];
3789a747e4fSDavid du Colombier 
3799a747e4fSDavid du Colombier static void
remember(ulong pc,void * v)3809a747e4fSDavid du Colombier remember(ulong pc, void *v)
3819a747e4fSDavid du Colombier {
3829a747e4fSDavid du Colombier 	Bhdr *b;
3839a747e4fSDavid du Colombier 	int i;
3849a747e4fSDavid du Colombier 
3859a747e4fSDavid du Colombier 	if(v == nil)
3869a747e4fSDavid du Colombier 		return;
3879a747e4fSDavid du Colombier 
3889a747e4fSDavid du Colombier 	D2B(b, v);
3899a747e4fSDavid du Colombier 	if((b->size>>5) != 2)
3909a747e4fSDavid du Colombier 		return;
3919a747e4fSDavid du Colombier 
3929a747e4fSDavid du Colombier 	ilock(&pcxlock);
3939a747e4fSDavid du Colombier 	B2T(b)->pad = 0;
3949a747e4fSDavid du Colombier 	for(i = 0; i < 1024; i++)
3959a747e4fSDavid du Colombier 		if(pcx[i].pc == pc || pcx[i].pc == 0){
3969a747e4fSDavid du Colombier 			pcx[i].pc = pc;
3979a747e4fSDavid du Colombier 			pcx[i].n++;
3989a747e4fSDavid du Colombier 			B2T(b)->pad = i;
3999a747e4fSDavid du Colombier 			break;
4009a747e4fSDavid du Colombier 		}
4019a747e4fSDavid du Colombier 	iunlock(&pcxlock);
4029a747e4fSDavid du Colombier }
4039a747e4fSDavid du Colombier 
4049a747e4fSDavid du Colombier static void
forget(void * v)4059a747e4fSDavid du Colombier forget(void *v)
4069a747e4fSDavid du Colombier {
4079a747e4fSDavid du Colombier 	Bhdr *b;
4089a747e4fSDavid du Colombier 
4099a747e4fSDavid du Colombier 	if(v == nil)
4109a747e4fSDavid du Colombier 		return;
4119a747e4fSDavid du Colombier 
4129a747e4fSDavid du Colombier 	D2B(b, v);
4139a747e4fSDavid du Colombier 	if((b->size>>5) != 2)
4149a747e4fSDavid du Colombier 		return;
4159a747e4fSDavid du Colombier 
4169a747e4fSDavid du Colombier 	ilock(&pcxlock);
4179a747e4fSDavid du Colombier 	pcx[B2T(b)->pad].n--;
4189a747e4fSDavid du Colombier 	iunlock(&pcxlock);
4199a747e4fSDavid du Colombier }
4209a747e4fSDavid du Colombier 
4219a747e4fSDavid du Colombier void*
malloc(ulong size)4229a747e4fSDavid du Colombier malloc(ulong size)
4239a747e4fSDavid du Colombier {
4249a747e4fSDavid du Colombier 	void *v;
4259a747e4fSDavid du Colombier 
4269a747e4fSDavid du Colombier 	v = poolalloc(mainmem, size);
4279a747e4fSDavid du Colombier remember(getcallerpc(&size), v);
4289a747e4fSDavid du Colombier 	if(v != nil)
4299a747e4fSDavid du Colombier 		memset(v, 0, size);
4309a747e4fSDavid du Colombier 	return v;
4319a747e4fSDavid du Colombier }
4329a747e4fSDavid du Colombier 
4339a747e4fSDavid du Colombier void*
smalloc(ulong size)4349a747e4fSDavid du Colombier smalloc(ulong size)
4359a747e4fSDavid du Colombier {
4369a747e4fSDavid du Colombier 	void *v;
4379a747e4fSDavid du Colombier 
4389a747e4fSDavid du Colombier 	for(;;) {
4399a747e4fSDavid du Colombier 		v = poolalloc(mainmem, size);
4409a747e4fSDavid du Colombier remember(getcallerpc(&size), v);
4419a747e4fSDavid du Colombier 		if(v != nil)
4429a747e4fSDavid du Colombier 			break;
4439a747e4fSDavid du Colombier 		tsleep(&up->sleep, return0, 0, 100);
4449a747e4fSDavid du Colombier 	}
4459a747e4fSDavid du Colombier 	memset(v, 0, size);
4469a747e4fSDavid du Colombier 	return v;
4479a747e4fSDavid du Colombier }
4489a747e4fSDavid du Colombier 
4499a747e4fSDavid du Colombier void*
mallocz(ulong size,int clr)4509a747e4fSDavid du Colombier mallocz(ulong size, int clr)
4519a747e4fSDavid du Colombier {
4529a747e4fSDavid du Colombier 	void *v;
4539a747e4fSDavid du Colombier 
4549a747e4fSDavid du Colombier 	v = poolalloc(mainmem, size);
4559a747e4fSDavid du Colombier remember(getcallerpc(&size), v);
4569a747e4fSDavid du Colombier 	if(clr && v != nil)
4579a747e4fSDavid du Colombier 		memset(v, 0, size);
4589a747e4fSDavid du Colombier 	return v;
4599a747e4fSDavid du Colombier }
4609a747e4fSDavid du Colombier 
4619a747e4fSDavid du Colombier void
free(void * v)4629a747e4fSDavid du Colombier free(void *v)
4639a747e4fSDavid du Colombier {
4649a747e4fSDavid du Colombier 	Bhdr *b;
4659a747e4fSDavid du Colombier 
4669a747e4fSDavid du Colombier 	if(v != nil) {
4679a747e4fSDavid du Colombier forget(v);
4689a747e4fSDavid du Colombier 		D2B(b, v);
4699a747e4fSDavid du Colombier 		poolfree(mainmem, v);
4709a747e4fSDavid du Colombier 	}
4719a747e4fSDavid du Colombier }
4729a747e4fSDavid du Colombier 
4739a747e4fSDavid du Colombier void*
realloc(void * v,ulong size)4749a747e4fSDavid du Colombier realloc(void *v, ulong size)
4759a747e4fSDavid du Colombier {
4769a747e4fSDavid du Colombier 	Bhdr *b;
4779a747e4fSDavid du Colombier 	void *nv;
4789a747e4fSDavid du Colombier 	int osize;
4799a747e4fSDavid du Colombier 
4809a747e4fSDavid du Colombier 	if(v == nil)
4819a747e4fSDavid du Colombier 		return malloc(size);
4829a747e4fSDavid du Colombier 
4839a747e4fSDavid du Colombier 	D2B(b, v);
4849a747e4fSDavid du Colombier 
4859a747e4fSDavid du Colombier 	osize = b->size - BHDRSIZE;
4869a747e4fSDavid du Colombier 	if(osize >= size)
4879a747e4fSDavid du Colombier 		return v;
4889a747e4fSDavid du Colombier 
4899a747e4fSDavid du Colombier 	nv = poolalloc(mainmem, size);
4909a747e4fSDavid du Colombier remember(getcallerpc(&v), nv);
4919a747e4fSDavid du Colombier 	if(nv != nil) {
4929a747e4fSDavid du Colombier 		memmove(nv, v, osize);
4939a747e4fSDavid du Colombier 		free(v);
4949a747e4fSDavid du Colombier 	}
4959a747e4fSDavid du Colombier 	return nv;
4969a747e4fSDavid du Colombier }
4979a747e4fSDavid du Colombier 
4989a747e4fSDavid du Colombier int
msize(void * v)4999a747e4fSDavid du Colombier msize(void *v)
5009a747e4fSDavid du Colombier {
5019a747e4fSDavid du Colombier 	Bhdr *b;
5029a747e4fSDavid du Colombier 
5039a747e4fSDavid du Colombier 	D2B(b, v);
5049a747e4fSDavid du Colombier 	return b->size - BHDRSIZE;
5059a747e4fSDavid du Colombier }
5069a747e4fSDavid du Colombier 
5079a747e4fSDavid du Colombier void*
calloc(ulong n,ulong szelem)5089a747e4fSDavid du Colombier calloc(ulong n, ulong szelem)
5099a747e4fSDavid du Colombier {
5109a747e4fSDavid du Colombier 	return malloc(n*szelem);
5119a747e4fSDavid du Colombier }
5129a747e4fSDavid du Colombier 
5139a747e4fSDavid du Colombier /*
5149a747e4fSDavid du Colombier void
5159a747e4fSDavid du Colombier pooldump(Bhdr *b, int d, int c)
5169a747e4fSDavid du Colombier {
5179a747e4fSDavid du Colombier 	Bhdr *t;
5189a747e4fSDavid du Colombier 
5199a747e4fSDavid du Colombier 	if(b == nil)
5209a747e4fSDavid du Colombier 		return;
5219a747e4fSDavid du Colombier 
5229a747e4fSDavid du Colombier 	print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n",
5239a747e4fSDavid du Colombier 		b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
5249a747e4fSDavid du Colombier 	d++;
5259a747e4fSDavid du Colombier 	for(t = b->fwd; t != b; t = t->fwd)
5269a747e4fSDavid du Colombier 		print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
5279a747e4fSDavid du Colombier 	pooldump(b->left, d, 'l');
5289a747e4fSDavid du Colombier 	pooldump(b->right, d, 'r');
5299a747e4fSDavid du Colombier }
5309a747e4fSDavid du Colombier 
5319a747e4fSDavid du Colombier 
5329a747e4fSDavid du Colombier void
5339a747e4fSDavid du Colombier poolshow(void)
5349a747e4fSDavid du Colombier {
5359a747e4fSDavid du Colombier 	int i;
5369a747e4fSDavid du Colombier 
5379a747e4fSDavid du Colombier 	for(i = 0; i < table.n; i++) {
5389a747e4fSDavid du Colombier 		print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
5399a747e4fSDavid du Colombier 		pooldump(table.pool[i].root, 0, 'R');
5409a747e4fSDavid du Colombier 	}
5419a747e4fSDavid du Colombier }
5429a747e4fSDavid du Colombier */
5439a747e4fSDavid du Colombier 
5449a747e4fSDavid du Colombier void
poolsummary(void)5459a747e4fSDavid du Colombier poolsummary(void)
5469a747e4fSDavid du Colombier {
5479a747e4fSDavid du Colombier 	int i;
5489a747e4fSDavid du Colombier 
5499a747e4fSDavid du Colombier 	for(i = 0; i < table.n; i++)
5509a747e4fSDavid du Colombier 		print("Arena: %s cursize=%lud; maxsize=%lud\n",
5519a747e4fSDavid du Colombier 			table.pool[i].name,
5529a747e4fSDavid du Colombier 			table.pool[i].cursize,
5539a747e4fSDavid du Colombier 			table.pool[i].maxsize);
5549a747e4fSDavid du Colombier }
5559a747e4fSDavid du Colombier 
5569a747e4fSDavid du Colombier /*
5579a747e4fSDavid du Colombier void
5589a747e4fSDavid du Colombier pooldump(Pool *p)
5599a747e4fSDavid du Colombier {
5609a747e4fSDavid du Colombier 	Bhdr *b, *base, *limit, *ptr;
5619a747e4fSDavid du Colombier 
5629a747e4fSDavid du Colombier 	b = p->chain;
5639a747e4fSDavid du Colombier 	if(b == nil)
5649a747e4fSDavid du Colombier 		return;
5659a747e4fSDavid du Colombier 	base = b;
5669a747e4fSDavid du Colombier 	ptr = b;
5679a747e4fSDavid du Colombier 	limit = B2LIMIT(b);
5689a747e4fSDavid du Colombier 
5699a747e4fSDavid du Colombier 	while(base != nil) {
5709a747e4fSDavid du Colombier 		print("\tbase #%.8lux ptr #%.8lux", base, ptr);
5719a747e4fSDavid du Colombier 		if(ptr->magic == MAGIC_A)
5729a747e4fSDavid du Colombier 			print("\tA%.5d\n", ptr->size);
5739a747e4fSDavid du Colombier 		else if(ptr->magic == MAGIC_E)
5749a747e4fSDavid du Colombier 			print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize);
5759a747e4fSDavid du Colombier 		else
5769a747e4fSDavid du Colombier 			print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n",
5779a747e4fSDavid du Colombier 				ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
5789a747e4fSDavid du Colombier 		ptr = B2NB(ptr);
5799a747e4fSDavid du Colombier 		if(ptr >= limit) {
5809a747e4fSDavid du Colombier 			print("link to #%.8lux\n", base->clink);
5819a747e4fSDavid du Colombier 			base = base->clink;
5829a747e4fSDavid du Colombier 			if(base == nil)
5839a747e4fSDavid du Colombier 				break;
5849a747e4fSDavid du Colombier 			ptr = base;
5859a747e4fSDavid du Colombier 			limit = B2LIMIT(base);
5869a747e4fSDavid du Colombier 		}
5879a747e4fSDavid du Colombier 	}
5889a747e4fSDavid du Colombier 	return;
5899a747e4fSDavid du Colombier }
5909a747e4fSDavid du Colombier */
5919a747e4fSDavid du Colombier 
5929a747e4fSDavid du Colombier void
poolsetcompact(Pool * p,void (* move)(void *,void *))5939a747e4fSDavid du Colombier poolsetcompact(Pool *p, void (*move)(void*, void*))
5949a747e4fSDavid du Colombier {
5959a747e4fSDavid du Colombier 	p->move = move;
5969a747e4fSDavid du Colombier }
5979a747e4fSDavid du Colombier 
5989a747e4fSDavid du Colombier void
poolsetparam(char * name,ulong maxsize,int quanta,int chunk)5999a747e4fSDavid du Colombier poolsetparam(char *name, ulong maxsize, int quanta, int chunk)
6009a747e4fSDavid du Colombier {
6019a747e4fSDavid du Colombier 	Pool *p;
6029a747e4fSDavid du Colombier 	int i;
6039a747e4fSDavid du Colombier 
6049a747e4fSDavid du Colombier 	for(i=0; i<table.n; i++){
6059a747e4fSDavid du Colombier 		p = &table.pool[i];
6069a747e4fSDavid du Colombier 		if(strcmp(name, p->name) == 0){
6079a747e4fSDavid du Colombier 			if(maxsize)
6089a747e4fSDavid du Colombier 				p->maxsize = maxsize;
6099a747e4fSDavid du Colombier 			if(quanta)
6109a747e4fSDavid du Colombier 				p->quanta = quanta;
6119a747e4fSDavid du Colombier 			if(chunk)
6129a747e4fSDavid du Colombier 				p->chunk = chunk;
6139a747e4fSDavid du Colombier 			return;
6149a747e4fSDavid du Colombier 		}
6159a747e4fSDavid du Colombier 	}
6169a747e4fSDavid du Colombier }
6179a747e4fSDavid du Colombier 
6189a747e4fSDavid du Colombier int
poolcompact(Pool * pool)6199a747e4fSDavid du Colombier poolcompact(Pool *pool)
6209a747e4fSDavid du Colombier {
6219a747e4fSDavid du Colombier 	Bhdr *base, *limit, *ptr, *end, *next;
6229a747e4fSDavid du Colombier 	int compacted, recov, nb;
6239a747e4fSDavid du Colombier 
6249a747e4fSDavid du Colombier 	if(pool->move == nil || pool->lastfree == pool->nfree)
6259a747e4fSDavid du Colombier 		return 0;
6269a747e4fSDavid du Colombier 
6279a747e4fSDavid du Colombier 	pool->lastfree = pool->nfree;
6289a747e4fSDavid du Colombier 
6299a747e4fSDavid du Colombier 	base = pool->chain;
6309a747e4fSDavid du Colombier 	ptr = B2NB(base);	/* First Block in arena has clink */
6319a747e4fSDavid du Colombier 	limit = B2LIMIT(base);
6329a747e4fSDavid du Colombier 	compacted = 0;
6339a747e4fSDavid du Colombier 
6349a747e4fSDavid du Colombier 	pool->root = nil;
6359a747e4fSDavid du Colombier 	end = ptr;
6369a747e4fSDavid du Colombier 	recov = 0;
6379a747e4fSDavid du Colombier 	while(base != nil) {
6389a747e4fSDavid du Colombier 		next = B2NB(ptr);
6399a747e4fSDavid du Colombier 		if(ptr->magic == MAGIC_A) {
6409a747e4fSDavid du Colombier 			if(ptr != end) {
6419a747e4fSDavid du Colombier 				memmove(end, ptr, ptr->size);
6429a747e4fSDavid du Colombier 				pool->move(B2D(ptr), B2D(end));
6439a747e4fSDavid du Colombier 				recov = (uchar*)ptr - (uchar*)end;
6449a747e4fSDavid du Colombier 				compacted = 1;
6459a747e4fSDavid du Colombier 			}
6469a747e4fSDavid du Colombier 			end = B2NB(end);
6479a747e4fSDavid du Colombier 		}
6489a747e4fSDavid du Colombier 		if(next >= limit) {
6499a747e4fSDavid du Colombier 			nb = (uchar*)limit - (uchar*)end;
6509a747e4fSDavid du Colombier 			//print("recovered %d bytes\n", recov);
6519a747e4fSDavid du Colombier 			//print("%d bytes at end\n", nb);
6529a747e4fSDavid du Colombier 			USED(recov);
6539a747e4fSDavid du Colombier 			if(nb > 0){
6549a747e4fSDavid du Colombier 				if(nb < pool->quanta+1)
6559a747e4fSDavid du Colombier 					panic("poolcompact: leftover too small\n");
6569a747e4fSDavid du Colombier 				end->size = nb;
6579a747e4fSDavid du Colombier 				pooladd(pool, end);
6589a747e4fSDavid du Colombier 			}
6599a747e4fSDavid du Colombier 			base = base->clink;
6609a747e4fSDavid du Colombier 			if(base == nil)
6619a747e4fSDavid du Colombier 				break;
6629a747e4fSDavid du Colombier 			ptr = B2NB(base);
6639a747e4fSDavid du Colombier 			end = ptr;	/* could do better by copying between chains */
6649a747e4fSDavid du Colombier 			limit = B2LIMIT(base);
6659a747e4fSDavid du Colombier 			recov = 0;
6669a747e4fSDavid du Colombier 		} else
6679a747e4fSDavid du Colombier 			ptr = next;
6689a747e4fSDavid du Colombier 	}
6699a747e4fSDavid du Colombier 
6709a747e4fSDavid du Colombier 	return compacted;
6719a747e4fSDavid du Colombier }
6729a747e4fSDavid du Colombier 
6739a747e4fSDavid du Colombier int
recur(Bhdr * t)6749a747e4fSDavid du Colombier recur(Bhdr *t)
6759a747e4fSDavid du Colombier {
6769a747e4fSDavid du Colombier 	if(t == 0)
6779a747e4fSDavid du Colombier 		return 1;
678*72061b92SDavid du Colombier 	if((uintptr)t < KZERO || (uintptr)t - KZERO > 0x10000000)
6799a747e4fSDavid du Colombier 		return 0;
6809a747e4fSDavid du Colombier 	return recur(t->right) && recur(t->left);
6819a747e4fSDavid du Colombier }
682