xref: /inferno-os/os/port/alloc.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "../port/lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "interp.h"
7*74a4d8c2SCharles.Forsyth 
8*74a4d8c2SCharles.Forsyth #define left	u.s.bhl
9*74a4d8c2SCharles.Forsyth #define right	u.s.bhr
10*74a4d8c2SCharles.Forsyth #define fwd	u.s.bhf
11*74a4d8c2SCharles.Forsyth #define prev	u.s.bhv
12*74a4d8c2SCharles.Forsyth #define parent	u.s.bhp
13*74a4d8c2SCharles.Forsyth 
14*74a4d8c2SCharles.Forsyth #define RESERVED	256*1024
15*74a4d8c2SCharles.Forsyth 
16*74a4d8c2SCharles.Forsyth struct Pool
17*74a4d8c2SCharles.Forsyth {
18*74a4d8c2SCharles.Forsyth 	char*	name;
19*74a4d8c2SCharles.Forsyth 	int	pnum;
20*74a4d8c2SCharles.Forsyth 	ulong	maxsize;
21*74a4d8c2SCharles.Forsyth 	int	quanta;
22*74a4d8c2SCharles.Forsyth 	int	chunk;
23*74a4d8c2SCharles.Forsyth 	ulong	ressize;
24*74a4d8c2SCharles.Forsyth 	ulong	cursize;
25*74a4d8c2SCharles.Forsyth 	ulong	arenasize;
26*74a4d8c2SCharles.Forsyth 	ulong	hw;
27*74a4d8c2SCharles.Forsyth 	Lock	l;
28*74a4d8c2SCharles.Forsyth 	Bhdr*	root;
29*74a4d8c2SCharles.Forsyth 	Bhdr*	chain;
30*74a4d8c2SCharles.Forsyth 	ulong	nalloc;
31*74a4d8c2SCharles.Forsyth 	ulong	nfree;
32*74a4d8c2SCharles.Forsyth 	int	nbrk;
33*74a4d8c2SCharles.Forsyth 	int	lastfree;
34*74a4d8c2SCharles.Forsyth 	int	warn;
35*74a4d8c2SCharles.Forsyth 	void	(*move)(void*, void*);
36*74a4d8c2SCharles.Forsyth };
37*74a4d8c2SCharles.Forsyth 
38*74a4d8c2SCharles.Forsyth static
39*74a4d8c2SCharles.Forsyth struct
40*74a4d8c2SCharles.Forsyth {
41*74a4d8c2SCharles.Forsyth 	int	n;
42*74a4d8c2SCharles.Forsyth 	Pool	pool[MAXPOOL];
43*74a4d8c2SCharles.Forsyth 	// Lock	l;
44*74a4d8c2SCharles.Forsyth } table = {
45*74a4d8c2SCharles.Forsyth 	3,
46*74a4d8c2SCharles.Forsyth 	{
47*74a4d8c2SCharles.Forsyth 		{ "main",  0,	 4*1024*1024, 31,  128*1024, 15*256*1024 },
48*74a4d8c2SCharles.Forsyth 		{ "heap",  1,	16*1024*1024, 31,  128*1024, 15*1024*1024 },
49*74a4d8c2SCharles.Forsyth 		{ "image", 2,	 8*1024*1024, 31, 300*1024, 15*512*1024 },
50*74a4d8c2SCharles.Forsyth 	}
51*74a4d8c2SCharles.Forsyth };
52*74a4d8c2SCharles.Forsyth 
53*74a4d8c2SCharles.Forsyth Pool*	mainmem = &table.pool[0];
54*74a4d8c2SCharles.Forsyth Pool*	heapmem = &table.pool[1];
55*74a4d8c2SCharles.Forsyth Pool*	imagmem = &table.pool[2];
56*74a4d8c2SCharles.Forsyth 
57*74a4d8c2SCharles.Forsyth static void _auditmemloc(char *, void *);
58*74a4d8c2SCharles.Forsyth void (*auditmemloc)(char *, void *) = _auditmemloc;
59*74a4d8c2SCharles.Forsyth static void _poolfault(void *, char *, ulong);
60*74a4d8c2SCharles.Forsyth void (*poolfault)(void *, char *, ulong) = _poolfault;
61*74a4d8c2SCharles.Forsyth 
62*74a4d8c2SCharles.Forsyth /*	non tracing
63*74a4d8c2SCharles.Forsyth  *
64*74a4d8c2SCharles.Forsyth enum {
65*74a4d8c2SCharles.Forsyth 	Npadlong	= 0,
66*74a4d8c2SCharles.Forsyth 	MallocOffset = 0,
67*74a4d8c2SCharles.Forsyth 	ReallocOffset = 0
68*74a4d8c2SCharles.Forsyth };
69*74a4d8c2SCharles.Forsyth  *
70*74a4d8c2SCharles.Forsyth  */
71*74a4d8c2SCharles.Forsyth 
72*74a4d8c2SCharles.Forsyth /* tracing */
73*74a4d8c2SCharles.Forsyth enum {
74*74a4d8c2SCharles.Forsyth 	Npadlong	= 2,
75*74a4d8c2SCharles.Forsyth 	MallocOffset = 0,
76*74a4d8c2SCharles.Forsyth 	ReallocOffset = 1
77*74a4d8c2SCharles.Forsyth };
78*74a4d8c2SCharles.Forsyth 
79*74a4d8c2SCharles.Forsyth int
memusehigh(void)80*74a4d8c2SCharles.Forsyth memusehigh(void)
81*74a4d8c2SCharles.Forsyth {
82*74a4d8c2SCharles.Forsyth 	return 	mainmem->cursize > mainmem->ressize ||
83*74a4d8c2SCharles.Forsyth 			heapmem->cursize > heapmem->ressize ||
84*74a4d8c2SCharles.Forsyth 			imagmem->cursize > imagmem->ressize;
85*74a4d8c2SCharles.Forsyth }
86*74a4d8c2SCharles.Forsyth 
87*74a4d8c2SCharles.Forsyth void
poolimmutable(void * v)88*74a4d8c2SCharles.Forsyth poolimmutable(void *v)
89*74a4d8c2SCharles.Forsyth {
90*74a4d8c2SCharles.Forsyth 	Bhdr *b;
91*74a4d8c2SCharles.Forsyth 
92*74a4d8c2SCharles.Forsyth 	D2B(b, v);
93*74a4d8c2SCharles.Forsyth 	b->magic = MAGIC_I;
94*74a4d8c2SCharles.Forsyth }
95*74a4d8c2SCharles.Forsyth 
96*74a4d8c2SCharles.Forsyth void
poolmutable(void * v)97*74a4d8c2SCharles.Forsyth poolmutable(void *v)
98*74a4d8c2SCharles.Forsyth {
99*74a4d8c2SCharles.Forsyth 	Bhdr *b;
100*74a4d8c2SCharles.Forsyth 
101*74a4d8c2SCharles.Forsyth 	D2B(b, v);
102*74a4d8c2SCharles.Forsyth 	b->magic = MAGIC_A;
103*74a4d8c2SCharles.Forsyth 	((Heap*)v)->color = mutator;
104*74a4d8c2SCharles.Forsyth }
105*74a4d8c2SCharles.Forsyth 
106*74a4d8c2SCharles.Forsyth char*
poolname(Pool * p)107*74a4d8c2SCharles.Forsyth poolname(Pool *p)
108*74a4d8c2SCharles.Forsyth {
109*74a4d8c2SCharles.Forsyth 	return p->name;
110*74a4d8c2SCharles.Forsyth }
111*74a4d8c2SCharles.Forsyth 
112*74a4d8c2SCharles.Forsyth Bhdr*
poolchain(Pool * p)113*74a4d8c2SCharles.Forsyth poolchain(Pool *p)
114*74a4d8c2SCharles.Forsyth {
115*74a4d8c2SCharles.Forsyth 	return p->chain;
116*74a4d8c2SCharles.Forsyth }
117*74a4d8c2SCharles.Forsyth 
118*74a4d8c2SCharles.Forsyth void
pooldel(Pool * p,Bhdr * t)119*74a4d8c2SCharles.Forsyth pooldel(Pool *p, Bhdr *t)
120*74a4d8c2SCharles.Forsyth {
121*74a4d8c2SCharles.Forsyth 	Bhdr *s, *f, *rp, *q;
122*74a4d8c2SCharles.Forsyth 
123*74a4d8c2SCharles.Forsyth 	if(t->parent == nil && p->root != t) {
124*74a4d8c2SCharles.Forsyth 		t->prev->fwd = t->fwd;
125*74a4d8c2SCharles.Forsyth 		t->fwd->prev = t->prev;
126*74a4d8c2SCharles.Forsyth 		return;
127*74a4d8c2SCharles.Forsyth 	}
128*74a4d8c2SCharles.Forsyth 
129*74a4d8c2SCharles.Forsyth 	if(t->fwd != t) {
130*74a4d8c2SCharles.Forsyth 		f = t->fwd;
131*74a4d8c2SCharles.Forsyth 		s = t->parent;
132*74a4d8c2SCharles.Forsyth 		f->parent = s;
133*74a4d8c2SCharles.Forsyth 		if(s == nil)
134*74a4d8c2SCharles.Forsyth 			p->root = f;
135*74a4d8c2SCharles.Forsyth 		else {
136*74a4d8c2SCharles.Forsyth 			if(s->left == t)
137*74a4d8c2SCharles.Forsyth 				s->left = f;
138*74a4d8c2SCharles.Forsyth 			else
139*74a4d8c2SCharles.Forsyth 				s->right = f;
140*74a4d8c2SCharles.Forsyth 		}
141*74a4d8c2SCharles.Forsyth 
142*74a4d8c2SCharles.Forsyth 		rp = t->left;
143*74a4d8c2SCharles.Forsyth 		f->left = rp;
144*74a4d8c2SCharles.Forsyth 		if(rp != nil)
145*74a4d8c2SCharles.Forsyth 			rp->parent = f;
146*74a4d8c2SCharles.Forsyth 		rp = t->right;
147*74a4d8c2SCharles.Forsyth 		f->right = rp;
148*74a4d8c2SCharles.Forsyth 		if(rp != nil)
149*74a4d8c2SCharles.Forsyth 			rp->parent = f;
150*74a4d8c2SCharles.Forsyth 
151*74a4d8c2SCharles.Forsyth 		t->prev->fwd = t->fwd;
152*74a4d8c2SCharles.Forsyth 		t->fwd->prev = t->prev;
153*74a4d8c2SCharles.Forsyth 		return;
154*74a4d8c2SCharles.Forsyth 	}
155*74a4d8c2SCharles.Forsyth 
156*74a4d8c2SCharles.Forsyth 	if(t->left == nil)
157*74a4d8c2SCharles.Forsyth 		rp = t->right;
158*74a4d8c2SCharles.Forsyth 	else {
159*74a4d8c2SCharles.Forsyth 		if(t->right == nil)
160*74a4d8c2SCharles.Forsyth 			rp = t->left;
161*74a4d8c2SCharles.Forsyth 		else {
162*74a4d8c2SCharles.Forsyth 			f = t;
163*74a4d8c2SCharles.Forsyth 			rp = t->right;
164*74a4d8c2SCharles.Forsyth 			s = rp->left;
165*74a4d8c2SCharles.Forsyth 			while(s != nil) {
166*74a4d8c2SCharles.Forsyth 				f = rp;
167*74a4d8c2SCharles.Forsyth 				rp = s;
168*74a4d8c2SCharles.Forsyth 				s = rp->left;
169*74a4d8c2SCharles.Forsyth 			}
170*74a4d8c2SCharles.Forsyth 			if(f != t) {
171*74a4d8c2SCharles.Forsyth 				s = rp->right;
172*74a4d8c2SCharles.Forsyth 				f->left = s;
173*74a4d8c2SCharles.Forsyth 				if(s != nil)
174*74a4d8c2SCharles.Forsyth 					s->parent = f;
175*74a4d8c2SCharles.Forsyth 				s = t->right;
176*74a4d8c2SCharles.Forsyth 				rp->right = s;
177*74a4d8c2SCharles.Forsyth 				if(s != nil)
178*74a4d8c2SCharles.Forsyth 					s->parent = rp;
179*74a4d8c2SCharles.Forsyth 			}
180*74a4d8c2SCharles.Forsyth 			s = t->left;
181*74a4d8c2SCharles.Forsyth 			rp->left = s;
182*74a4d8c2SCharles.Forsyth 			s->parent = rp;
183*74a4d8c2SCharles.Forsyth 		}
184*74a4d8c2SCharles.Forsyth 	}
185*74a4d8c2SCharles.Forsyth 	q = t->parent;
186*74a4d8c2SCharles.Forsyth 	if(q == nil)
187*74a4d8c2SCharles.Forsyth 		p->root = rp;
188*74a4d8c2SCharles.Forsyth 	else {
189*74a4d8c2SCharles.Forsyth 		if(t == q->left)
190*74a4d8c2SCharles.Forsyth 			q->left = rp;
191*74a4d8c2SCharles.Forsyth 		else
192*74a4d8c2SCharles.Forsyth 			q->right = rp;
193*74a4d8c2SCharles.Forsyth 	}
194*74a4d8c2SCharles.Forsyth 	if(rp != nil)
195*74a4d8c2SCharles.Forsyth 		rp->parent = q;
196*74a4d8c2SCharles.Forsyth }
197*74a4d8c2SCharles.Forsyth 
198*74a4d8c2SCharles.Forsyth void
pooladd(Pool * p,Bhdr * q)199*74a4d8c2SCharles.Forsyth pooladd(Pool *p, Bhdr *q)
200*74a4d8c2SCharles.Forsyth {
201*74a4d8c2SCharles.Forsyth 	int size;
202*74a4d8c2SCharles.Forsyth 	Bhdr *tp, *t;
203*74a4d8c2SCharles.Forsyth 
204*74a4d8c2SCharles.Forsyth 	q->magic = MAGIC_F;
205*74a4d8c2SCharles.Forsyth 
206*74a4d8c2SCharles.Forsyth 	q->left = nil;
207*74a4d8c2SCharles.Forsyth 	q->right = nil;
208*74a4d8c2SCharles.Forsyth 	q->parent = nil;
209*74a4d8c2SCharles.Forsyth 	q->fwd = q;
210*74a4d8c2SCharles.Forsyth 	q->prev = q;
211*74a4d8c2SCharles.Forsyth 
212*74a4d8c2SCharles.Forsyth 	t = p->root;
213*74a4d8c2SCharles.Forsyth 	if(t == nil) {
214*74a4d8c2SCharles.Forsyth 		p->root = q;
215*74a4d8c2SCharles.Forsyth 		return;
216*74a4d8c2SCharles.Forsyth 	}
217*74a4d8c2SCharles.Forsyth 
218*74a4d8c2SCharles.Forsyth 	size = q->size;
219*74a4d8c2SCharles.Forsyth 
220*74a4d8c2SCharles.Forsyth 	tp = nil;
221*74a4d8c2SCharles.Forsyth 	while(t != nil) {
222*74a4d8c2SCharles.Forsyth 		if(size == t->size) {
223*74a4d8c2SCharles.Forsyth 			q->prev = t->prev;
224*74a4d8c2SCharles.Forsyth 			q->prev->fwd = q;
225*74a4d8c2SCharles.Forsyth 			q->fwd = t;
226*74a4d8c2SCharles.Forsyth 			t->prev = q;
227*74a4d8c2SCharles.Forsyth 			return;
228*74a4d8c2SCharles.Forsyth 		}
229*74a4d8c2SCharles.Forsyth 		tp = t;
230*74a4d8c2SCharles.Forsyth 		if(size < t->size)
231*74a4d8c2SCharles.Forsyth 			t = t->left;
232*74a4d8c2SCharles.Forsyth 		else
233*74a4d8c2SCharles.Forsyth 			t = t->right;
234*74a4d8c2SCharles.Forsyth 	}
235*74a4d8c2SCharles.Forsyth 
236*74a4d8c2SCharles.Forsyth 	q->parent = tp;
237*74a4d8c2SCharles.Forsyth 	if(size < tp->size)
238*74a4d8c2SCharles.Forsyth 		tp->left = q;
239*74a4d8c2SCharles.Forsyth 	else
240*74a4d8c2SCharles.Forsyth 		tp->right = q;
241*74a4d8c2SCharles.Forsyth }
242*74a4d8c2SCharles.Forsyth 
243*74a4d8c2SCharles.Forsyth void
poolsummary(void)244*74a4d8c2SCharles.Forsyth poolsummary(void)
245*74a4d8c2SCharles.Forsyth {
246*74a4d8c2SCharles.Forsyth 	int x = 0;
247*74a4d8c2SCharles.Forsyth 	char buf[400];
248*74a4d8c2SCharles.Forsyth 
249*74a4d8c2SCharles.Forsyth 	print("\n");
250*74a4d8c2SCharles.Forsyth 	print("    cursize     maxsize       hw         nalloc       nfree      nbrk       max      name\n");
251*74a4d8c2SCharles.Forsyth 
252*74a4d8c2SCharles.Forsyth 	x=poolread( buf, sizeof buf - 1, x );
253*74a4d8c2SCharles.Forsyth 	buf[x] = 0;
254*74a4d8c2SCharles.Forsyth 	putstrn(buf, x);
255*74a4d8c2SCharles.Forsyth 	print("\n");
256*74a4d8c2SCharles.Forsyth }
257*74a4d8c2SCharles.Forsyth 
258*74a4d8c2SCharles.Forsyth void*
poolalloc(Pool * p,ulong asize)259*74a4d8c2SCharles.Forsyth poolalloc(Pool *p, ulong asize)
260*74a4d8c2SCharles.Forsyth {
261*74a4d8c2SCharles.Forsyth 	Bhdr *q, *t;
262*74a4d8c2SCharles.Forsyth 	int alloc, ldr, ns, frag;
263*74a4d8c2SCharles.Forsyth 	int osize, size;
264*74a4d8c2SCharles.Forsyth 	Prog *prog;
265*74a4d8c2SCharles.Forsyth 
266*74a4d8c2SCharles.Forsyth 	if(asize >= 1024*1024*1024)	/* for sanity and to avoid overflow */
267*74a4d8c2SCharles.Forsyth 		return nil;
268*74a4d8c2SCharles.Forsyth 	if(p->cursize > p->ressize && (prog = currun()) != nil && prog->flags&Prestricted)
269*74a4d8c2SCharles.Forsyth 		return nil;
270*74a4d8c2SCharles.Forsyth 	size = asize;
271*74a4d8c2SCharles.Forsyth 	osize = size;
272*74a4d8c2SCharles.Forsyth 	size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
273*74a4d8c2SCharles.Forsyth 
274*74a4d8c2SCharles.Forsyth 	ilock(&p->l);
275*74a4d8c2SCharles.Forsyth 	p->nalloc++;
276*74a4d8c2SCharles.Forsyth 
277*74a4d8c2SCharles.Forsyth 	t = p->root;
278*74a4d8c2SCharles.Forsyth 	q = nil;
279*74a4d8c2SCharles.Forsyth 	while(t) {
280*74a4d8c2SCharles.Forsyth 		if(t->size == size) {
281*74a4d8c2SCharles.Forsyth 			t = t->fwd;
282*74a4d8c2SCharles.Forsyth 			pooldel(p, t);
283*74a4d8c2SCharles.Forsyth 			t->magic = MAGIC_A;
284*74a4d8c2SCharles.Forsyth 			p->cursize += t->size;
285*74a4d8c2SCharles.Forsyth 			if(p->cursize > p->hw)
286*74a4d8c2SCharles.Forsyth 				p->hw = p->cursize;
287*74a4d8c2SCharles.Forsyth 			iunlock(&p->l);
288*74a4d8c2SCharles.Forsyth 			return B2D(t);
289*74a4d8c2SCharles.Forsyth 		}
290*74a4d8c2SCharles.Forsyth 		if(size < t->size) {
291*74a4d8c2SCharles.Forsyth 			q = t;
292*74a4d8c2SCharles.Forsyth 			t = t->left;
293*74a4d8c2SCharles.Forsyth 		}
294*74a4d8c2SCharles.Forsyth 		else
295*74a4d8c2SCharles.Forsyth 			t = t->right;
296*74a4d8c2SCharles.Forsyth 	}
297*74a4d8c2SCharles.Forsyth 	if(q != nil) {
298*74a4d8c2SCharles.Forsyth 		pooldel(p, q);
299*74a4d8c2SCharles.Forsyth 		q->magic = MAGIC_A;
300*74a4d8c2SCharles.Forsyth 		frag = q->size - size;
301*74a4d8c2SCharles.Forsyth 		if(frag < (size>>2) && frag < 0x8000) {
302*74a4d8c2SCharles.Forsyth 			p->cursize += q->size;
303*74a4d8c2SCharles.Forsyth 			if(p->cursize > p->hw)
304*74a4d8c2SCharles.Forsyth 				p->hw = p->cursize;
305*74a4d8c2SCharles.Forsyth 			iunlock(&p->l);
306*74a4d8c2SCharles.Forsyth 			return B2D(q);
307*74a4d8c2SCharles.Forsyth 		}
308*74a4d8c2SCharles.Forsyth 		/* Split */
309*74a4d8c2SCharles.Forsyth 		ns = q->size - size;
310*74a4d8c2SCharles.Forsyth 		q->size = size;
311*74a4d8c2SCharles.Forsyth 		B2T(q)->hdr = q;
312*74a4d8c2SCharles.Forsyth 		t = B2NB(q);
313*74a4d8c2SCharles.Forsyth 		t->size = ns;
314*74a4d8c2SCharles.Forsyth 		B2T(t)->hdr = t;
315*74a4d8c2SCharles.Forsyth 		pooladd(p, t);
316*74a4d8c2SCharles.Forsyth 		p->cursize += q->size;
317*74a4d8c2SCharles.Forsyth 		if(p->cursize > p->hw)
318*74a4d8c2SCharles.Forsyth 			p->hw = p->cursize;
319*74a4d8c2SCharles.Forsyth 		iunlock(&p->l);
320*74a4d8c2SCharles.Forsyth 		return B2D(q);
321*74a4d8c2SCharles.Forsyth 	}
322*74a4d8c2SCharles.Forsyth 
323*74a4d8c2SCharles.Forsyth 	ns = p->chunk;
324*74a4d8c2SCharles.Forsyth 	if(size > ns)
325*74a4d8c2SCharles.Forsyth 		ns = size;
326*74a4d8c2SCharles.Forsyth 	ldr = p->quanta+1;
327*74a4d8c2SCharles.Forsyth 
328*74a4d8c2SCharles.Forsyth 	alloc = ns+ldr+ldr;
329*74a4d8c2SCharles.Forsyth 	p->arenasize += alloc;
330*74a4d8c2SCharles.Forsyth 	if(p->arenasize > p->maxsize) {
331*74a4d8c2SCharles.Forsyth 		p->arenasize -= alloc;
332*74a4d8c2SCharles.Forsyth 		ns = p->maxsize-p->arenasize-ldr-ldr;
333*74a4d8c2SCharles.Forsyth 		ns &= ~p->quanta;
334*74a4d8c2SCharles.Forsyth 		if (ns < size) {
335*74a4d8c2SCharles.Forsyth 			if(poolcompact(p)) {
336*74a4d8c2SCharles.Forsyth 				iunlock(&p->l);
337*74a4d8c2SCharles.Forsyth 				return poolalloc(p, osize);
338*74a4d8c2SCharles.Forsyth 			}
339*74a4d8c2SCharles.Forsyth 
340*74a4d8c2SCharles.Forsyth 			iunlock(&p->l);
341*74a4d8c2SCharles.Forsyth 			if(p->warn)
342*74a4d8c2SCharles.Forsyth 				return nil;
343*74a4d8c2SCharles.Forsyth 			p->warn = 1;
344*74a4d8c2SCharles.Forsyth 			if (p != mainmem || ns > 512)
345*74a4d8c2SCharles.Forsyth 				print("arena too large: %s size %d cursize %lud arenasize %lud maxsize %lud, alloc = %d\n", p->name, osize, p->cursize, p->arenasize, p->maxsize, alloc);
346*74a4d8c2SCharles.Forsyth 			return nil;
347*74a4d8c2SCharles.Forsyth 		}
348*74a4d8c2SCharles.Forsyth 		alloc = ns+ldr+ldr;
349*74a4d8c2SCharles.Forsyth 		p->arenasize += alloc;
350*74a4d8c2SCharles.Forsyth 	}
351*74a4d8c2SCharles.Forsyth 
352*74a4d8c2SCharles.Forsyth 	p->nbrk++;
353*74a4d8c2SCharles.Forsyth 	t = xalloc(alloc);
354*74a4d8c2SCharles.Forsyth 	if(t == nil) {
355*74a4d8c2SCharles.Forsyth 		p->nbrk--;
356*74a4d8c2SCharles.Forsyth 		iunlock(&p->l);
357*74a4d8c2SCharles.Forsyth 		return nil;
358*74a4d8c2SCharles.Forsyth 	}
359*74a4d8c2SCharles.Forsyth 	/* Double alignment */
360*74a4d8c2SCharles.Forsyth 	t = (Bhdr *)(((ulong)t + 7) & ~7);
361*74a4d8c2SCharles.Forsyth 
362*74a4d8c2SCharles.Forsyth 	/* TBS xmerge */
363*74a4d8c2SCharles.Forsyth 	if(0 && p->chain != nil && (char*)t-(char*)B2LIMIT(p->chain)-ldr == 0){
364*74a4d8c2SCharles.Forsyth 		/* can merge chains */
365*74a4d8c2SCharles.Forsyth 		if(0)print("merging chains %p and %p in %s\n", p->chain, t, p->name);
366*74a4d8c2SCharles.Forsyth 		q = B2LIMIT(p->chain);
367*74a4d8c2SCharles.Forsyth 		q->magic = MAGIC_A;
368*74a4d8c2SCharles.Forsyth 		q->size = alloc;
369*74a4d8c2SCharles.Forsyth 		B2T(q)->hdr = q;
370*74a4d8c2SCharles.Forsyth 		t = B2NB(q);
371*74a4d8c2SCharles.Forsyth 		t->magic = MAGIC_E;
372*74a4d8c2SCharles.Forsyth 		p->chain->csize += alloc;
373*74a4d8c2SCharles.Forsyth 		p->cursize += alloc;
374*74a4d8c2SCharles.Forsyth 		iunlock(&p->l);
375*74a4d8c2SCharles.Forsyth 		poolfree(p, B2D(q));		/* for backward merge */
376*74a4d8c2SCharles.Forsyth 		return poolalloc(p, osize);
377*74a4d8c2SCharles.Forsyth 	}
378*74a4d8c2SCharles.Forsyth 
379*74a4d8c2SCharles.Forsyth 	t->magic = MAGIC_E;		/* Make a leader */
380*74a4d8c2SCharles.Forsyth 	t->size = ldr;
381*74a4d8c2SCharles.Forsyth 	t->csize = ns+ldr;
382*74a4d8c2SCharles.Forsyth 	t->clink = p->chain;
383*74a4d8c2SCharles.Forsyth 	p->chain = t;
384*74a4d8c2SCharles.Forsyth 	B2T(t)->hdr = t;
385*74a4d8c2SCharles.Forsyth 	t = B2NB(t);
386*74a4d8c2SCharles.Forsyth 
387*74a4d8c2SCharles.Forsyth 	t->magic = MAGIC_A;		/* Make the block we are going to return */
388*74a4d8c2SCharles.Forsyth 	t->size = size;
389*74a4d8c2SCharles.Forsyth 	B2T(t)->hdr = t;
390*74a4d8c2SCharles.Forsyth 	q = t;
391*74a4d8c2SCharles.Forsyth 
392*74a4d8c2SCharles.Forsyth 	ns -= size;			/* Free the rest */
393*74a4d8c2SCharles.Forsyth 	if(ns > 0) {
394*74a4d8c2SCharles.Forsyth 		q = B2NB(t);
395*74a4d8c2SCharles.Forsyth 		q->size = ns;
396*74a4d8c2SCharles.Forsyth 		B2T(q)->hdr = q;
397*74a4d8c2SCharles.Forsyth 		pooladd(p, q);
398*74a4d8c2SCharles.Forsyth 	}
399*74a4d8c2SCharles.Forsyth 	B2NB(q)->magic = MAGIC_E;	/* Mark the end of the chunk */
400*74a4d8c2SCharles.Forsyth 
401*74a4d8c2SCharles.Forsyth 	p->cursize += t->size;
402*74a4d8c2SCharles.Forsyth 	if(p->cursize > p->hw)
403*74a4d8c2SCharles.Forsyth 		p->hw = p->cursize;
404*74a4d8c2SCharles.Forsyth 	iunlock(&p->l);
405*74a4d8c2SCharles.Forsyth 	return B2D(t);
406*74a4d8c2SCharles.Forsyth }
407*74a4d8c2SCharles.Forsyth 
408*74a4d8c2SCharles.Forsyth void
poolfree(Pool * p,void * v)409*74a4d8c2SCharles.Forsyth poolfree(Pool *p, void *v)
410*74a4d8c2SCharles.Forsyth {
411*74a4d8c2SCharles.Forsyth 	Bhdr *b, *c;
412*74a4d8c2SCharles.Forsyth 	extern Bhdr *ptr;
413*74a4d8c2SCharles.Forsyth 
414*74a4d8c2SCharles.Forsyth 	D2B(b, v);
415*74a4d8c2SCharles.Forsyth 
416*74a4d8c2SCharles.Forsyth 	ilock(&p->l);
417*74a4d8c2SCharles.Forsyth 	p->nfree++;
418*74a4d8c2SCharles.Forsyth 	p->cursize -= b->size;
419*74a4d8c2SCharles.Forsyth 
420*74a4d8c2SCharles.Forsyth 	c = B2NB(b);
421*74a4d8c2SCharles.Forsyth 	if(c->magic == MAGIC_F) {	/* Join forward */
422*74a4d8c2SCharles.Forsyth 		if(c == ptr)
423*74a4d8c2SCharles.Forsyth 			ptr = b;
424*74a4d8c2SCharles.Forsyth 		pooldel(p, c);
425*74a4d8c2SCharles.Forsyth 		c->magic = 0;
426*74a4d8c2SCharles.Forsyth 		b->size += c->size;
427*74a4d8c2SCharles.Forsyth 		B2T(b)->hdr = b;
428*74a4d8c2SCharles.Forsyth 	}
429*74a4d8c2SCharles.Forsyth 
430*74a4d8c2SCharles.Forsyth 	c = B2PT(b)->hdr;
431*74a4d8c2SCharles.Forsyth 	if(c->magic == MAGIC_F) {	/* Join backward */
432*74a4d8c2SCharles.Forsyth 		if(b == ptr)
433*74a4d8c2SCharles.Forsyth 			ptr = c;
434*74a4d8c2SCharles.Forsyth 		pooldel(p, c);
435*74a4d8c2SCharles.Forsyth 		b->magic = 0;
436*74a4d8c2SCharles.Forsyth 		c->size += b->size;
437*74a4d8c2SCharles.Forsyth 		b = c;
438*74a4d8c2SCharles.Forsyth 		B2T(b)->hdr = b;
439*74a4d8c2SCharles.Forsyth 	}
440*74a4d8c2SCharles.Forsyth 
441*74a4d8c2SCharles.Forsyth 	pooladd(p, b);
442*74a4d8c2SCharles.Forsyth 	iunlock(&p->l);
443*74a4d8c2SCharles.Forsyth }
444*74a4d8c2SCharles.Forsyth 
445*74a4d8c2SCharles.Forsyth void *
poolrealloc(Pool * p,void * v,ulong size)446*74a4d8c2SCharles.Forsyth poolrealloc(Pool *p, void *v, ulong size)
447*74a4d8c2SCharles.Forsyth {
448*74a4d8c2SCharles.Forsyth 	Bhdr *b;
449*74a4d8c2SCharles.Forsyth 	void *nv;
450*74a4d8c2SCharles.Forsyth 	int osize;
451*74a4d8c2SCharles.Forsyth 
452*74a4d8c2SCharles.Forsyth 	if(size >= 1024*1024*1024)	/* for sanity and to avoid overflow */
453*74a4d8c2SCharles.Forsyth 		return nil;
454*74a4d8c2SCharles.Forsyth 	if(size == 0){
455*74a4d8c2SCharles.Forsyth 		poolfree(p, v);
456*74a4d8c2SCharles.Forsyth 		return nil;
457*74a4d8c2SCharles.Forsyth 	}
458*74a4d8c2SCharles.Forsyth 	SET(osize);
459*74a4d8c2SCharles.Forsyth 	if(v != nil){
460*74a4d8c2SCharles.Forsyth 		ilock(&p->l);
461*74a4d8c2SCharles.Forsyth 		D2B(b, v);
462*74a4d8c2SCharles.Forsyth 		osize = b->size - BHDRSIZE;
463*74a4d8c2SCharles.Forsyth 		iunlock(&p->l);
464*74a4d8c2SCharles.Forsyth 		if(osize >= size)
465*74a4d8c2SCharles.Forsyth 			return v;
466*74a4d8c2SCharles.Forsyth 	}
467*74a4d8c2SCharles.Forsyth 	nv = poolalloc(p, size);
468*74a4d8c2SCharles.Forsyth 	if(nv != nil && v != nil){
469*74a4d8c2SCharles.Forsyth 		memmove(nv, v, osize);
470*74a4d8c2SCharles.Forsyth 		poolfree(p, v);
471*74a4d8c2SCharles.Forsyth 	}
472*74a4d8c2SCharles.Forsyth 	return nv;
473*74a4d8c2SCharles.Forsyth }
474*74a4d8c2SCharles.Forsyth 
475*74a4d8c2SCharles.Forsyth ulong
poolmsize(Pool * p,void * v)476*74a4d8c2SCharles.Forsyth poolmsize(Pool *p, void *v)
477*74a4d8c2SCharles.Forsyth {
478*74a4d8c2SCharles.Forsyth 	Bhdr *b;
479*74a4d8c2SCharles.Forsyth 	ulong size;
480*74a4d8c2SCharles.Forsyth 
481*74a4d8c2SCharles.Forsyth 	if(v == nil)
482*74a4d8c2SCharles.Forsyth 		return 0;
483*74a4d8c2SCharles.Forsyth 	ilock(&p->l);
484*74a4d8c2SCharles.Forsyth 	D2B(b, v);
485*74a4d8c2SCharles.Forsyth 	size = b->size - BHDRSIZE;
486*74a4d8c2SCharles.Forsyth 	iunlock(&p->l);
487*74a4d8c2SCharles.Forsyth 	return size;
488*74a4d8c2SCharles.Forsyth }
489*74a4d8c2SCharles.Forsyth 
490*74a4d8c2SCharles.Forsyth static ulong
poolmax(Pool * p)491*74a4d8c2SCharles.Forsyth poolmax(Pool *p)
492*74a4d8c2SCharles.Forsyth {
493*74a4d8c2SCharles.Forsyth 	Bhdr *t;
494*74a4d8c2SCharles.Forsyth 	ulong size;
495*74a4d8c2SCharles.Forsyth 
496*74a4d8c2SCharles.Forsyth 	ilock(&p->l);
497*74a4d8c2SCharles.Forsyth 	size = p->maxsize - p->cursize;
498*74a4d8c2SCharles.Forsyth 	t = p->root;
499*74a4d8c2SCharles.Forsyth 	if(t != nil) {
500*74a4d8c2SCharles.Forsyth 		while(t->right != nil)
501*74a4d8c2SCharles.Forsyth 			t = t->right;
502*74a4d8c2SCharles.Forsyth 		if(size < t->size)
503*74a4d8c2SCharles.Forsyth 			size = t->size;
504*74a4d8c2SCharles.Forsyth 	}
505*74a4d8c2SCharles.Forsyth 	if(size >= BHDRSIZE)
506*74a4d8c2SCharles.Forsyth 		size -= BHDRSIZE;
507*74a4d8c2SCharles.Forsyth 	iunlock(&p->l);
508*74a4d8c2SCharles.Forsyth 	return size;
509*74a4d8c2SCharles.Forsyth }
510*74a4d8c2SCharles.Forsyth 
511*74a4d8c2SCharles.Forsyth int
poolread(char * va,int count,ulong offset)512*74a4d8c2SCharles.Forsyth poolread(char *va, int count, ulong offset)
513*74a4d8c2SCharles.Forsyth {
514*74a4d8c2SCharles.Forsyth 	Pool *p;
515*74a4d8c2SCharles.Forsyth 	int n, i, signed_off;
516*74a4d8c2SCharles.Forsyth 
517*74a4d8c2SCharles.Forsyth 	n = 0;
518*74a4d8c2SCharles.Forsyth 	signed_off = offset;
519*74a4d8c2SCharles.Forsyth 	for(i = 0; i < table.n; i++) {
520*74a4d8c2SCharles.Forsyth 		p = &table.pool[i];
521*74a4d8c2SCharles.Forsyth 		n += snprint(va+n, count-n, "%11lud %11lud %11lud %11lud %11lud %11d %11lud %s\n",
522*74a4d8c2SCharles.Forsyth 			p->cursize,
523*74a4d8c2SCharles.Forsyth 			p->maxsize,
524*74a4d8c2SCharles.Forsyth 			p->hw,
525*74a4d8c2SCharles.Forsyth 			p->nalloc,
526*74a4d8c2SCharles.Forsyth 			p->nfree,
527*74a4d8c2SCharles.Forsyth 			p->nbrk,
528*74a4d8c2SCharles.Forsyth 			poolmax(p),
529*74a4d8c2SCharles.Forsyth 			p->name);
530*74a4d8c2SCharles.Forsyth 
531*74a4d8c2SCharles.Forsyth 		if(signed_off > 0) {
532*74a4d8c2SCharles.Forsyth 			signed_off -= n;
533*74a4d8c2SCharles.Forsyth 			if(signed_off < 0) {
534*74a4d8c2SCharles.Forsyth 				memmove(va, va+n+signed_off, -signed_off);
535*74a4d8c2SCharles.Forsyth 				n = -signed_off;
536*74a4d8c2SCharles.Forsyth 			}
537*74a4d8c2SCharles.Forsyth 			else
538*74a4d8c2SCharles.Forsyth 				n = 0;
539*74a4d8c2SCharles.Forsyth 		}
540*74a4d8c2SCharles.Forsyth 
541*74a4d8c2SCharles.Forsyth 	}
542*74a4d8c2SCharles.Forsyth 	return n;
543*74a4d8c2SCharles.Forsyth }
544*74a4d8c2SCharles.Forsyth 
545*74a4d8c2SCharles.Forsyth void*
malloc(ulong size)546*74a4d8c2SCharles.Forsyth malloc(ulong size)
547*74a4d8c2SCharles.Forsyth {
548*74a4d8c2SCharles.Forsyth 	void *v;
549*74a4d8c2SCharles.Forsyth 
550*74a4d8c2SCharles.Forsyth 	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
551*74a4d8c2SCharles.Forsyth 	if(v != nil){
552*74a4d8c2SCharles.Forsyth 		if(Npadlong){
553*74a4d8c2SCharles.Forsyth 			v = (ulong*)v+Npadlong;
554*74a4d8c2SCharles.Forsyth 			setmalloctag(v, getcallerpc(&size));
555*74a4d8c2SCharles.Forsyth 			setrealloctag(v, 0);
556*74a4d8c2SCharles.Forsyth 		}
557*74a4d8c2SCharles.Forsyth 		memset(v, 0, size);
558*74a4d8c2SCharles.Forsyth 	}
559*74a4d8c2SCharles.Forsyth 	return v;
560*74a4d8c2SCharles.Forsyth }
561*74a4d8c2SCharles.Forsyth 
562*74a4d8c2SCharles.Forsyth void*
smalloc(ulong size)563*74a4d8c2SCharles.Forsyth smalloc(ulong size)
564*74a4d8c2SCharles.Forsyth {
565*74a4d8c2SCharles.Forsyth 	void *v;
566*74a4d8c2SCharles.Forsyth 
567*74a4d8c2SCharles.Forsyth 	for(;;) {
568*74a4d8c2SCharles.Forsyth 		v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
569*74a4d8c2SCharles.Forsyth 		if(v != nil)
570*74a4d8c2SCharles.Forsyth 			break;
571*74a4d8c2SCharles.Forsyth 		tsleep(&up->sleep, return0, 0, 100);
572*74a4d8c2SCharles.Forsyth 	}
573*74a4d8c2SCharles.Forsyth 	if(Npadlong){
574*74a4d8c2SCharles.Forsyth 		v = (ulong*)v+Npadlong;
575*74a4d8c2SCharles.Forsyth 		setmalloctag(v, getcallerpc(&size));
576*74a4d8c2SCharles.Forsyth 		setrealloctag(v, 0);
577*74a4d8c2SCharles.Forsyth 	}
578*74a4d8c2SCharles.Forsyth 	memset(v, 0, size);
579*74a4d8c2SCharles.Forsyth 	return v;
580*74a4d8c2SCharles.Forsyth }
581*74a4d8c2SCharles.Forsyth 
582*74a4d8c2SCharles.Forsyth void*
mallocz(ulong size,int clr)583*74a4d8c2SCharles.Forsyth mallocz(ulong size, int clr)
584*74a4d8c2SCharles.Forsyth {
585*74a4d8c2SCharles.Forsyth 	void *v;
586*74a4d8c2SCharles.Forsyth 
587*74a4d8c2SCharles.Forsyth 	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
588*74a4d8c2SCharles.Forsyth 	if(v != nil){
589*74a4d8c2SCharles.Forsyth 		if(Npadlong){
590*74a4d8c2SCharles.Forsyth 			v = (ulong*)v+Npadlong;
591*74a4d8c2SCharles.Forsyth 			setmalloctag(v, getcallerpc(&size));
592*74a4d8c2SCharles.Forsyth 			setrealloctag(v, 0);
593*74a4d8c2SCharles.Forsyth 		}
594*74a4d8c2SCharles.Forsyth 		if(clr)
595*74a4d8c2SCharles.Forsyth 			memset(v, 0, size);
596*74a4d8c2SCharles.Forsyth 	}
597*74a4d8c2SCharles.Forsyth 	return v;
598*74a4d8c2SCharles.Forsyth }
599*74a4d8c2SCharles.Forsyth 
600*74a4d8c2SCharles.Forsyth void
free(void * v)601*74a4d8c2SCharles.Forsyth free(void *v)
602*74a4d8c2SCharles.Forsyth {
603*74a4d8c2SCharles.Forsyth 	Bhdr *b;
604*74a4d8c2SCharles.Forsyth 
605*74a4d8c2SCharles.Forsyth 	if(v != nil) {
606*74a4d8c2SCharles.Forsyth 		if(Npadlong)
607*74a4d8c2SCharles.Forsyth 			v = (ulong*)v-Npadlong;
608*74a4d8c2SCharles.Forsyth 		D2B(b, v);
609*74a4d8c2SCharles.Forsyth 		poolfree(mainmem, v);
610*74a4d8c2SCharles.Forsyth 	}
611*74a4d8c2SCharles.Forsyth }
612*74a4d8c2SCharles.Forsyth 
613*74a4d8c2SCharles.Forsyth void*
realloc(void * v,ulong size)614*74a4d8c2SCharles.Forsyth realloc(void *v, ulong size)
615*74a4d8c2SCharles.Forsyth {
616*74a4d8c2SCharles.Forsyth 	void *nv;
617*74a4d8c2SCharles.Forsyth 
618*74a4d8c2SCharles.Forsyth 	if(size == 0)
619*74a4d8c2SCharles.Forsyth 		return malloc(size);	/* temporary change until realloc calls can be checked */
620*74a4d8c2SCharles.Forsyth 	if(v != nil)
621*74a4d8c2SCharles.Forsyth 		v = (ulong*)v-Npadlong;
622*74a4d8c2SCharles.Forsyth 	if(Npadlong!=0 && size!=0)
623*74a4d8c2SCharles.Forsyth 		size += Npadlong*sizeof(ulong);
624*74a4d8c2SCharles.Forsyth 	nv = poolrealloc(mainmem, v, size);
625*74a4d8c2SCharles.Forsyth 	if(nv != nil) {
626*74a4d8c2SCharles.Forsyth 		nv = (ulong*)nv+Npadlong;
627*74a4d8c2SCharles.Forsyth 		setrealloctag(nv, getcallerpc(&v));
628*74a4d8c2SCharles.Forsyth 		if(v == nil)
629*74a4d8c2SCharles.Forsyth 			setmalloctag(v, getcallerpc(&v));
630*74a4d8c2SCharles.Forsyth 	}
631*74a4d8c2SCharles.Forsyth 	return nv;
632*74a4d8c2SCharles.Forsyth }
633*74a4d8c2SCharles.Forsyth 
634*74a4d8c2SCharles.Forsyth void
setmalloctag(void * v,ulong pc)635*74a4d8c2SCharles.Forsyth setmalloctag(void *v, ulong pc)
636*74a4d8c2SCharles.Forsyth {
637*74a4d8c2SCharles.Forsyth 	ulong *u;
638*74a4d8c2SCharles.Forsyth 
639*74a4d8c2SCharles.Forsyth 	USED(v);
640*74a4d8c2SCharles.Forsyth 	USED(pc);
641*74a4d8c2SCharles.Forsyth 	if(Npadlong <= MallocOffset || v == nil)
642*74a4d8c2SCharles.Forsyth 		return;
643*74a4d8c2SCharles.Forsyth 	u = v;
644*74a4d8c2SCharles.Forsyth 	u[-Npadlong+MallocOffset] = pc;
645*74a4d8c2SCharles.Forsyth }
646*74a4d8c2SCharles.Forsyth 
647*74a4d8c2SCharles.Forsyth ulong
getmalloctag(void * v)648*74a4d8c2SCharles.Forsyth getmalloctag(void *v)
649*74a4d8c2SCharles.Forsyth {
650*74a4d8c2SCharles.Forsyth 	USED(v);
651*74a4d8c2SCharles.Forsyth 	if(Npadlong <= MallocOffset)
652*74a4d8c2SCharles.Forsyth 		return ~0;
653*74a4d8c2SCharles.Forsyth 	return ((ulong*)v)[-Npadlong+MallocOffset];
654*74a4d8c2SCharles.Forsyth }
655*74a4d8c2SCharles.Forsyth 
656*74a4d8c2SCharles.Forsyth void
setrealloctag(void * v,ulong pc)657*74a4d8c2SCharles.Forsyth setrealloctag(void *v, ulong pc)
658*74a4d8c2SCharles.Forsyth {
659*74a4d8c2SCharles.Forsyth 	ulong *u;
660*74a4d8c2SCharles.Forsyth 
661*74a4d8c2SCharles.Forsyth 	USED(v);
662*74a4d8c2SCharles.Forsyth 	USED(pc);
663*74a4d8c2SCharles.Forsyth 	if(Npadlong <= ReallocOffset || v == nil)
664*74a4d8c2SCharles.Forsyth 		return;
665*74a4d8c2SCharles.Forsyth 	u = v;
666*74a4d8c2SCharles.Forsyth 	u[-Npadlong+ReallocOffset] = pc;
667*74a4d8c2SCharles.Forsyth }
668*74a4d8c2SCharles.Forsyth 
669*74a4d8c2SCharles.Forsyth ulong
getrealloctag(void * v)670*74a4d8c2SCharles.Forsyth getrealloctag(void *v)
671*74a4d8c2SCharles.Forsyth {
672*74a4d8c2SCharles.Forsyth 	USED(v);
673*74a4d8c2SCharles.Forsyth 	if(Npadlong <= ReallocOffset)
674*74a4d8c2SCharles.Forsyth 		return ((ulong*)v)[-Npadlong+ReallocOffset];
675*74a4d8c2SCharles.Forsyth 	return ~0;
676*74a4d8c2SCharles.Forsyth }
677*74a4d8c2SCharles.Forsyth 
678*74a4d8c2SCharles.Forsyth ulong
msize(void * v)679*74a4d8c2SCharles.Forsyth msize(void *v)
680*74a4d8c2SCharles.Forsyth {
681*74a4d8c2SCharles.Forsyth 	if(v == nil)
682*74a4d8c2SCharles.Forsyth 		return 0;
683*74a4d8c2SCharles.Forsyth 	return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);
684*74a4d8c2SCharles.Forsyth }
685*74a4d8c2SCharles.Forsyth 
686*74a4d8c2SCharles.Forsyth void*
calloc(ulong n,ulong szelem)687*74a4d8c2SCharles.Forsyth calloc(ulong n, ulong szelem)
688*74a4d8c2SCharles.Forsyth {
689*74a4d8c2SCharles.Forsyth 	return malloc(n*szelem);
690*74a4d8c2SCharles.Forsyth }
691*74a4d8c2SCharles.Forsyth 
692*74a4d8c2SCharles.Forsyth void
pooldump(Bhdr * b,int d,int c)693*74a4d8c2SCharles.Forsyth pooldump(Bhdr *b, int d, int c)
694*74a4d8c2SCharles.Forsyth {
695*74a4d8c2SCharles.Forsyth 	Bhdr *t;
696*74a4d8c2SCharles.Forsyth 
697*74a4d8c2SCharles.Forsyth 	if(b == nil)
698*74a4d8c2SCharles.Forsyth 		return;
699*74a4d8c2SCharles.Forsyth 
700*74a4d8c2SCharles.Forsyth 	print("%.8lux %.8lux %.8lux %c %4d %lud (f %.8lux p %.8lux)\n",
701*74a4d8c2SCharles.Forsyth 		b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
702*74a4d8c2SCharles.Forsyth 	d++;
703*74a4d8c2SCharles.Forsyth 	for(t = b->fwd; t != b; t = t->fwd)
704*74a4d8c2SCharles.Forsyth 		print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
705*74a4d8c2SCharles.Forsyth 	pooldump(b->left, d, 'l');
706*74a4d8c2SCharles.Forsyth 	pooldump(b->right, d, 'r');
707*74a4d8c2SCharles.Forsyth }
708*74a4d8c2SCharles.Forsyth 
709*74a4d8c2SCharles.Forsyth void
poolshow(void)710*74a4d8c2SCharles.Forsyth poolshow(void)
711*74a4d8c2SCharles.Forsyth {
712*74a4d8c2SCharles.Forsyth 	int i;
713*74a4d8c2SCharles.Forsyth 
714*74a4d8c2SCharles.Forsyth 	for(i = 0; i < table.n; i++) {
715*74a4d8c2SCharles.Forsyth 		print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
716*74a4d8c2SCharles.Forsyth 		pooldump(table.pool[i].root, 0, 'R');
717*74a4d8c2SCharles.Forsyth 	}
718*74a4d8c2SCharles.Forsyth }
719*74a4d8c2SCharles.Forsyth 
720*74a4d8c2SCharles.Forsyth void
poolsetcompact(Pool * p,void (* move)(void *,void *))721*74a4d8c2SCharles.Forsyth poolsetcompact(Pool *p, void (*move)(void*, void*))
722*74a4d8c2SCharles.Forsyth {
723*74a4d8c2SCharles.Forsyth 	p->move = move;
724*74a4d8c2SCharles.Forsyth }
725*74a4d8c2SCharles.Forsyth 
726*74a4d8c2SCharles.Forsyth int
poolcompact(Pool * pool)727*74a4d8c2SCharles.Forsyth poolcompact(Pool *pool)
728*74a4d8c2SCharles.Forsyth {
729*74a4d8c2SCharles.Forsyth 	Bhdr *base, *limit, *ptr, *end, *next;
730*74a4d8c2SCharles.Forsyth 	int compacted, nb;
731*74a4d8c2SCharles.Forsyth 
732*74a4d8c2SCharles.Forsyth 	if(pool->move == nil || pool->lastfree == pool->nfree)
733*74a4d8c2SCharles.Forsyth 		return 0;
734*74a4d8c2SCharles.Forsyth 
735*74a4d8c2SCharles.Forsyth 	pool->lastfree = pool->nfree;
736*74a4d8c2SCharles.Forsyth 
737*74a4d8c2SCharles.Forsyth 	base = pool->chain;
738*74a4d8c2SCharles.Forsyth 	ptr = B2NB(base);	/* First Block in arena has clink */
739*74a4d8c2SCharles.Forsyth 	limit = B2LIMIT(base);
740*74a4d8c2SCharles.Forsyth 	compacted = 0;
741*74a4d8c2SCharles.Forsyth 
742*74a4d8c2SCharles.Forsyth 	pool->root = nil;
743*74a4d8c2SCharles.Forsyth 	end = ptr;
744*74a4d8c2SCharles.Forsyth 	while(base != nil) {
745*74a4d8c2SCharles.Forsyth 		next = B2NB(ptr);
746*74a4d8c2SCharles.Forsyth 		if(ptr->magic == MAGIC_A || ptr->magic == MAGIC_I) {
747*74a4d8c2SCharles.Forsyth 			if(ptr != end) {
748*74a4d8c2SCharles.Forsyth 				memmove(end, ptr, ptr->size);
749*74a4d8c2SCharles.Forsyth 				pool->move(B2D(ptr), B2D(end));
750*74a4d8c2SCharles.Forsyth 				compacted = 1;
751*74a4d8c2SCharles.Forsyth 			}
752*74a4d8c2SCharles.Forsyth 			end = B2NB(end);
753*74a4d8c2SCharles.Forsyth 		}
754*74a4d8c2SCharles.Forsyth 		if(next >= limit) {
755*74a4d8c2SCharles.Forsyth 			nb = (uchar*)limit - (uchar*)end;
756*74a4d8c2SCharles.Forsyth 			if(nb > 0){
757*74a4d8c2SCharles.Forsyth 				if(nb < pool->quanta+1)
758*74a4d8c2SCharles.Forsyth 					panic("poolcompact: leftover too small\n");
759*74a4d8c2SCharles.Forsyth 				end->size = nb;
760*74a4d8c2SCharles.Forsyth 				B2T(end)->hdr = end;
761*74a4d8c2SCharles.Forsyth 				pooladd(pool, end);
762*74a4d8c2SCharles.Forsyth 			}
763*74a4d8c2SCharles.Forsyth 			base = base->clink;
764*74a4d8c2SCharles.Forsyth 			if(base == nil)
765*74a4d8c2SCharles.Forsyth 				break;
766*74a4d8c2SCharles.Forsyth 			ptr = B2NB(base);
767*74a4d8c2SCharles.Forsyth 			end = ptr;	/* could do better by copying between chains */
768*74a4d8c2SCharles.Forsyth 			limit = B2LIMIT(base);
769*74a4d8c2SCharles.Forsyth 		} else
770*74a4d8c2SCharles.Forsyth 			ptr = next;
771*74a4d8c2SCharles.Forsyth 	}
772*74a4d8c2SCharles.Forsyth 
773*74a4d8c2SCharles.Forsyth 	return compacted;
774*74a4d8c2SCharles.Forsyth }
775*74a4d8c2SCharles.Forsyth 
776*74a4d8c2SCharles.Forsyth void
poolsize(Pool * p,int max,int contig)777*74a4d8c2SCharles.Forsyth poolsize(Pool *p, int max, int contig)
778*74a4d8c2SCharles.Forsyth {
779*74a4d8c2SCharles.Forsyth 	void *x;
780*74a4d8c2SCharles.Forsyth 
781*74a4d8c2SCharles.Forsyth 	p->maxsize = max;
782*74a4d8c2SCharles.Forsyth 	if(max == 0)
783*74a4d8c2SCharles.Forsyth 		p->ressize = max;
784*74a4d8c2SCharles.Forsyth 	else if(max < RESERVED)
785*74a4d8c2SCharles.Forsyth 		p->ressize = max;
786*74a4d8c2SCharles.Forsyth 	else
787*74a4d8c2SCharles.Forsyth 		p->ressize = max-RESERVED;
788*74a4d8c2SCharles.Forsyth 	if (contig && max > 0) {
789*74a4d8c2SCharles.Forsyth 		p->chunk = max-1024;
790*74a4d8c2SCharles.Forsyth 		x = poolalloc(p, p->chunk);
791*74a4d8c2SCharles.Forsyth 		if(x == nil)
792*74a4d8c2SCharles.Forsyth 			panic("poolsize: don't have %d bytes\n", p->chunk);
793*74a4d8c2SCharles.Forsyth 		poolfree(p, x);
794*74a4d8c2SCharles.Forsyth 		p->hw = 0;
795*74a4d8c2SCharles.Forsyth 	}
796*74a4d8c2SCharles.Forsyth }
797*74a4d8c2SCharles.Forsyth 
798*74a4d8c2SCharles.Forsyth static void
_poolfault(void * v,char * msg,ulong c)799*74a4d8c2SCharles.Forsyth _poolfault(void *v, char *msg, ulong c)
800*74a4d8c2SCharles.Forsyth {
801*74a4d8c2SCharles.Forsyth 	setpanic();
802*74a4d8c2SCharles.Forsyth 	auditmemloc(msg, v);
803*74a4d8c2SCharles.Forsyth 	panic("%s %lux (from %lux/%lux)", msg, v, getcallerpc(&v), c);
804*74a4d8c2SCharles.Forsyth }
805*74a4d8c2SCharles.Forsyth 
806*74a4d8c2SCharles.Forsyth static void
dumpvl(char * msg,ulong * v,int n)807*74a4d8c2SCharles.Forsyth dumpvl(char *msg, ulong *v, int n)
808*74a4d8c2SCharles.Forsyth {
809*74a4d8c2SCharles.Forsyth 	int i, l;
810*74a4d8c2SCharles.Forsyth 
811*74a4d8c2SCharles.Forsyth 	l = print("%s at %p: ", msg, v);
812*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n; i++) {
813*74a4d8c2SCharles.Forsyth 		if(l >= 60) {
814*74a4d8c2SCharles.Forsyth 			print("\n");
815*74a4d8c2SCharles.Forsyth 			l = print("    %p: ", v);
816*74a4d8c2SCharles.Forsyth 		}
817*74a4d8c2SCharles.Forsyth 		l += print(" %lux", *v++);
818*74a4d8c2SCharles.Forsyth 	}
819*74a4d8c2SCharles.Forsyth 	print("\n");
820*74a4d8c2SCharles.Forsyth 	USED(l);
821*74a4d8c2SCharles.Forsyth }
822*74a4d8c2SCharles.Forsyth 
823*74a4d8c2SCharles.Forsyth static void
corrupted(char * str,char * msg,Pool * p,Bhdr * b,void * v)824*74a4d8c2SCharles.Forsyth corrupted(char *str, char *msg, Pool *p, Bhdr *b, void *v)
825*74a4d8c2SCharles.Forsyth {
826*74a4d8c2SCharles.Forsyth 	print("%s(%p): pool %s CORRUPT: %s at %p'%lud(magic=%lux)\n",
827*74a4d8c2SCharles.Forsyth 		str, v, p->name, msg, b, b->size, b->magic);
828*74a4d8c2SCharles.Forsyth 	dumpvl("bad Bhdr", (ulong *)((ulong)b & ~3)-4, 10);
829*74a4d8c2SCharles.Forsyth }
830*74a4d8c2SCharles.Forsyth 
831*74a4d8c2SCharles.Forsyth static void
_auditmemloc(char * str,void * v)832*74a4d8c2SCharles.Forsyth _auditmemloc(char *str, void *v)
833*74a4d8c2SCharles.Forsyth {
834*74a4d8c2SCharles.Forsyth 	Pool *p;
835*74a4d8c2SCharles.Forsyth 	Bhdr *bc, *ec, *b, *nb, *fb = nil;
836*74a4d8c2SCharles.Forsyth 	char *fmsg, *msg;
837*74a4d8c2SCharles.Forsyth 	ulong fsz;
838*74a4d8c2SCharles.Forsyth 
839*74a4d8c2SCharles.Forsyth 	SET(fsz, fmsg);
840*74a4d8c2SCharles.Forsyth 	for (p = &table.pool[0]; p < &table.pool[nelem(table.pool)]; p++) {
841*74a4d8c2SCharles.Forsyth 		ilock(&p->l);
842*74a4d8c2SCharles.Forsyth 		for (bc = p->chain; bc != nil; bc = bc->clink) {
843*74a4d8c2SCharles.Forsyth 			if (bc->magic != MAGIC_E) {
844*74a4d8c2SCharles.Forsyth 				iunlock(&p->l);
845*74a4d8c2SCharles.Forsyth 				corrupted(str, "chain hdr!=MAGIC_E", p, bc, v);
846*74a4d8c2SCharles.Forsyth 				goto nextpool;
847*74a4d8c2SCharles.Forsyth 			}
848*74a4d8c2SCharles.Forsyth 			ec = B2LIMIT(bc);
849*74a4d8c2SCharles.Forsyth 			if (((Bhdr*)v >= bc) && ((Bhdr*)v < ec))
850*74a4d8c2SCharles.Forsyth 				goto found;
851*74a4d8c2SCharles.Forsyth 		}
852*74a4d8c2SCharles.Forsyth 		iunlock(&p->l);
853*74a4d8c2SCharles.Forsyth nextpool:	;
854*74a4d8c2SCharles.Forsyth 	}
855*74a4d8c2SCharles.Forsyth 	print("%s: %lux not in pools\n", str, v);
856*74a4d8c2SCharles.Forsyth 	return;
857*74a4d8c2SCharles.Forsyth 
858*74a4d8c2SCharles.Forsyth found:
859*74a4d8c2SCharles.Forsyth 	for (b = bc; b < ec; b = nb) {
860*74a4d8c2SCharles.Forsyth 		switch(b->magic) {
861*74a4d8c2SCharles.Forsyth 		case MAGIC_F:
862*74a4d8c2SCharles.Forsyth 			msg = "free blk";
863*74a4d8c2SCharles.Forsyth 			break;
864*74a4d8c2SCharles.Forsyth 		case MAGIC_I:
865*74a4d8c2SCharles.Forsyth 			msg = "immutable block";
866*74a4d8c2SCharles.Forsyth 			break;
867*74a4d8c2SCharles.Forsyth 		case MAGIC_A:
868*74a4d8c2SCharles.Forsyth 			msg = "block";
869*74a4d8c2SCharles.Forsyth 			break;
870*74a4d8c2SCharles.Forsyth 		default:
871*74a4d8c2SCharles.Forsyth 			if (b == bc && b->magic == MAGIC_E) {
872*74a4d8c2SCharles.Forsyth 				msg = "pool hdr";
873*74a4d8c2SCharles.Forsyth 				break;
874*74a4d8c2SCharles.Forsyth 			}
875*74a4d8c2SCharles.Forsyth 			iunlock(&p->l);
876*74a4d8c2SCharles.Forsyth 			corrupted(str, "bad magic", p, b, v);
877*74a4d8c2SCharles.Forsyth 			goto badchunk;
878*74a4d8c2SCharles.Forsyth 		}
879*74a4d8c2SCharles.Forsyth 		if (b->size <= 0 || (b->size & p->quanta)) {
880*74a4d8c2SCharles.Forsyth 			iunlock(&p->l);
881*74a4d8c2SCharles.Forsyth 			corrupted(str, "bad size", p, b, v);
882*74a4d8c2SCharles.Forsyth 			goto badchunk;
883*74a4d8c2SCharles.Forsyth 		}
884*74a4d8c2SCharles.Forsyth 		if (fb != nil)
885*74a4d8c2SCharles.Forsyth 			break;
886*74a4d8c2SCharles.Forsyth 		nb = B2NB(b);
887*74a4d8c2SCharles.Forsyth 		if ((Bhdr*)v < nb) {
888*74a4d8c2SCharles.Forsyth 			fb = b;
889*74a4d8c2SCharles.Forsyth 			fsz = b->size;
890*74a4d8c2SCharles.Forsyth 			fmsg = msg;
891*74a4d8c2SCharles.Forsyth 		}
892*74a4d8c2SCharles.Forsyth 	}
893*74a4d8c2SCharles.Forsyth 	iunlock(&p->l);
894*74a4d8c2SCharles.Forsyth 	if (b >= ec) {
895*74a4d8c2SCharles.Forsyth 		if (b > ec)
896*74a4d8c2SCharles.Forsyth 			corrupted(str, "chain size mismatch", p, b, v);
897*74a4d8c2SCharles.Forsyth 		else if (b->magic != MAGIC_E)
898*74a4d8c2SCharles.Forsyth 			corrupted(str, "chain end!=MAGIC_E", p, b, v);
899*74a4d8c2SCharles.Forsyth 	}
900*74a4d8c2SCharles.Forsyth badchunk:
901*74a4d8c2SCharles.Forsyth 	if (fb != nil) {
902*74a4d8c2SCharles.Forsyth 		print("%s: %lux in %s:", str, v, p->name);
903*74a4d8c2SCharles.Forsyth 		if (fb == v)
904*74a4d8c2SCharles.Forsyth 			print(" is %s '%lux\n", fmsg, fsz);
905*74a4d8c2SCharles.Forsyth 		else
906*74a4d8c2SCharles.Forsyth 			print(" in %s at %lux'%lux\n", fmsg, fb, fsz);
907*74a4d8c2SCharles.Forsyth 		dumpvl("area", (ulong *)((ulong)v & ~3)-4, 20);
908*74a4d8c2SCharles.Forsyth 	}
909*74a4d8c2SCharles.Forsyth }
910*74a4d8c2SCharles.Forsyth 
911*74a4d8c2SCharles.Forsyth char *
poolaudit(char * (* audit)(int,Bhdr *))912*74a4d8c2SCharles.Forsyth poolaudit(char*(*audit)(int, Bhdr *))
913*74a4d8c2SCharles.Forsyth {
914*74a4d8c2SCharles.Forsyth 	Pool *p;
915*74a4d8c2SCharles.Forsyth 	Bhdr *bc, *ec, *b;
916*74a4d8c2SCharles.Forsyth 	char *r = nil;
917*74a4d8c2SCharles.Forsyth 
918*74a4d8c2SCharles.Forsyth 	for (p = &table.pool[0]; p < &table.pool[nelem(table.pool)]; p++) {
919*74a4d8c2SCharles.Forsyth 		ilock(&p->l);
920*74a4d8c2SCharles.Forsyth 		for (bc = p->chain; bc != nil; bc = bc->clink) {
921*74a4d8c2SCharles.Forsyth 			if (bc->magic != MAGIC_E) {
922*74a4d8c2SCharles.Forsyth 				iunlock(&p->l);
923*74a4d8c2SCharles.Forsyth 				return "bad chain hdr";
924*74a4d8c2SCharles.Forsyth 			}
925*74a4d8c2SCharles.Forsyth 			ec = B2LIMIT(bc);
926*74a4d8c2SCharles.Forsyth 			for (b = bc; b < ec; b = B2NB(b)) {
927*74a4d8c2SCharles.Forsyth 				if (b->size <= 0 || (b->size & p->quanta))
928*74a4d8c2SCharles.Forsyth 					r = "bad size in bhdr";
929*74a4d8c2SCharles.Forsyth 				else
930*74a4d8c2SCharles.Forsyth 					switch(b->magic) {
931*74a4d8c2SCharles.Forsyth 					case MAGIC_E:
932*74a4d8c2SCharles.Forsyth 						if (b != bc) {
933*74a4d8c2SCharles.Forsyth 							r = "unexpected MAGIC_E";
934*74a4d8c2SCharles.Forsyth 							break;
935*74a4d8c2SCharles.Forsyth 						}
936*74a4d8c2SCharles.Forsyth 					case MAGIC_F:
937*74a4d8c2SCharles.Forsyth 					case MAGIC_A:
938*74a4d8c2SCharles.Forsyth 					case MAGIC_I:
939*74a4d8c2SCharles.Forsyth 						r = audit(p->pnum, b);
940*74a4d8c2SCharles.Forsyth 						break;
941*74a4d8c2SCharles.Forsyth 					default:
942*74a4d8c2SCharles.Forsyth 						r = "bad magic";
943*74a4d8c2SCharles.Forsyth 					}
944*74a4d8c2SCharles.Forsyth 				if (r != nil) {
945*74a4d8c2SCharles.Forsyth 					iunlock(&p->l);
946*74a4d8c2SCharles.Forsyth 					return r;
947*74a4d8c2SCharles.Forsyth 				}
948*74a4d8c2SCharles.Forsyth 			}
949*74a4d8c2SCharles.Forsyth 			if (b != ec || b->magic != MAGIC_E) {
950*74a4d8c2SCharles.Forsyth 				iunlock(&p->l);
951*74a4d8c2SCharles.Forsyth 				return "bad chain ending";
952*74a4d8c2SCharles.Forsyth 			}
953*74a4d8c2SCharles.Forsyth 		}
954*74a4d8c2SCharles.Forsyth 		iunlock(&p->l);
955*74a4d8c2SCharles.Forsyth 	}
956*74a4d8c2SCharles.Forsyth 	return r;
957*74a4d8c2SCharles.Forsyth }
958*74a4d8c2SCharles.Forsyth 
959*74a4d8c2SCharles.Forsyth void
poolinit(void)960*74a4d8c2SCharles.Forsyth poolinit(void)
961*74a4d8c2SCharles.Forsyth {
962*74a4d8c2SCharles.Forsyth 	debugkey('m', "memory pools", poolsummary, 0);
963*74a4d8c2SCharles.Forsyth }
964