2 #include "../port/lib.h"
13 #define parent u.s.bhp
15 typedef struct Bhdr Bhdr;
22 NOT_MAGIC = 0xdeadfa11,
41 void (*move)(void*, void*);
52 { "Main", 4*1024*1024, 31, 128*1024 },
53 { "Image", 16*1024*1024, 31, 2*1024*1024 },
57 Pool* mainmem = &table.pool[0];
58 Pool* imagmem = &table.pool[1];
60 int poolcompact(Pool*);
69 pooldel(Pool *p, Bhdr *t)
73 if(t->parent == nil && p->root != t) {
74 t->prev->fwd = t->fwd;
75 t->fwd->prev = t->prev;
101 t->prev->fwd = t->fwd;
102 t->fwd->prev = t->prev;
149 pooladd(Pool *p, Bhdr *q)
172 if(size == t->size) {
194 poolalloc(Pool *p, int size)
197 int alloc, ldr, ns, frag;
199 if(size < 0 || size >= 1024*1024*1024) /* for sanity and to avoid overflow */
201 size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
209 if(t->size == size) {
212 p->cursize += t->size;
213 if(p->cursize > p->hw)
228 frag = q->size - size;
229 if(frag < (size>>2)) {
230 p->cursize += q->size;
231 if(p->cursize > p->hw)
244 p->cursize += q->size;
245 if(p->cursize > p->hw)
256 alloc = ns+ldr+sizeof(t->magic);
257 p->arenasize += alloc;
258 if(p->arenasize > p->maxsize) {
259 p->arenasize -= alloc;
263 return poolalloc(p, size);
267 print("%s arena too large: size %d cursize %lud arenasize %lud maxsize %lud\n",
268 p->name, size, p->cursize, p->arenasize, p->maxsize);
279 t->magic = MAGIC_E; /* Make a leader */
287 t->magic = MAGIC_A; /* Make the block we are going to return */
292 ns -= size; /* Free the rest */
299 B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */
301 p->cursize += t->size;
302 if(p->cursize > p->hw)
309 poolfree(Pool *p, void *v)
317 p->cursize -= b->size;
320 if(c->magic == MAGIC_F) { /* Join forward */
328 if(c->magic == MAGIC_F) { /* Join backward */
341 poolread(char *va, int count, ulong offset)
344 int n, i, signed_off;
348 for(i = 0; i < table.n; i++) {
350 n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n",
362 memmove(va, va+n+signed_off, -signed_off);
380 remember(ulong pc, void *v)
389 if((b->size>>5) != 2)
394 for(i = 0; i < 1024; i++)
395 if(pcx[i].pc == pc || pcx[i].pc == 0){
413 if((b->size>>5) != 2)
417 pcx[B2T(b)->pad].n--;
426 v = poolalloc(mainmem, size);
427 remember(getcallerpc(&size), v);
439 v = poolalloc(mainmem, size);
440 remember(getcallerpc(&size), v);
444 tsleep(&up->sleep, return0, 0, 100);
453 mallocz(ulong size, int clr)
457 v = poolalloc(mainmem, size);
458 remember(getcallerpc(&size), v);
472 poolfree(mainmem, v);
477 realloc(void *v, ulong size)
488 osize = b->size - BHDRSIZE;
492 nv = poolalloc(mainmem, size);
493 remember(getcallerpc(&v), nv);
495 memmove(nv, v, osize);
507 return b->size - BHDRSIZE;
511 calloc(ulong n, ulong szelem)
513 return malloc(n*szelem);
518 pooldump(Bhdr *b, int d, int c)
525 print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n",
526 b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
528 for(t = b->fwd; t != b; t = t->fwd)
529 print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
530 pooldump(b->left, d, 'l');
531 pooldump(b->right, d, 'r');
540 for(i = 0; i < table.n; i++) {
541 print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
542 pooldump(table.pool[i].root, 0, 'R');
552 for(i = 0; i < table.n; i++)
553 print("Arena: %s cursize=%lud; maxsize=%lud\n",
555 table.pool[i].cursize,
556 table.pool[i].maxsize);
563 Bhdr *b, *base, *limit, *ptr;
573 print("\tbase #%.8lux ptr #%.8lux", base, ptr);
574 if(ptr->magic == MAGIC_A)
575 print("\tA%.5d\n", ptr->size);
576 else if(ptr->magic == MAGIC_E)
577 print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize);
579 print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n",
580 ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
583 print("link to #%.8lux\n", base->clink);
588 limit = B2LIMIT(base);
596 poolsetcompact(Pool *p, void (*move)(void*, void*))
602 poolsetparam(char *name, ulong maxsize, int quanta, int chunk)
607 for(i=0; i<table.n; i++){
609 if(strcmp(name, p->name) == 0){
611 p->maxsize = maxsize;
622 poolcompact(Pool *pool)
624 Bhdr *base, *limit, *ptr, *end, *next;
625 int compacted, recov, nb;
627 if(pool->move == nil || pool->lastfree == pool->nfree)
630 pool->lastfree = pool->nfree;
633 ptr = B2NB(base); /* First Block in arena has clink */
634 limit = B2LIMIT(base);
642 if(ptr->magic == MAGIC_A) {
644 memmove(end, ptr, ptr->size);
645 pool->move(B2D(ptr), B2D(end));
646 recov = (uchar*)ptr - (uchar*)end;
652 nb = (uchar*)limit - (uchar*)end;
653 //print("recovered %d bytes\n", recov);
654 //print("%d bytes at end\n", nb);
657 if(nb < pool->quanta+1)
658 panic("poolcompact: leftover too small\n");
666 end = ptr; /* could do better by copying between chains */
667 limit = B2LIMIT(base);
681 if((uintptr)t < KZERO || (uintptr)t - KZERO > 0x10000000)
683 return recur(t->right) && recur(t->left);