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