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