#include "dat.h"#include "fns.h"#include "interp.h"#include "error.h" enum{ MAXPOOL = 4}; #define left u.s.bhl#define right u.s.bhr#define fwd u.s.bhf#define prev u.s.bhv#define parent u.s.bhp #define RESERVED 512*1024 struct Pool{ char* name; int pnum; ulong maxsize; int quanta; int chunk; int monitor; ulong ressize; /* restricted size */ ulong cursize; ulong arenasize; ulong hw; Lock l; Bhdr* root; Bhdr* chain; ulong nalloc; ulong nfree; int nbrk; int lastfree; void (*move)(void*, void*);}; void* initbrk(ulong); struct{ int n; Pool pool[MAXPOOL]; /* Lock l; */} table = { 3, { { "main", 0, 32*1024*1024, 63, 512*1024, 0, 31*1024*1024 }, { "heap", 1, 32*1024*1024, 63, 512*1024, 0, 31*1024*1024 }, { "image", 2, 32*1024*1024+256, 63, 4*1024*1024, 1, 31*1024*1024 }, }}; Pool* mainmem = &table.pool[0];Pool* heapmem = &table.pool[1];Pool* imagmem = &table.pool[2]; static void _auditmemloc(char *, void *);void (*auditmemloc)(char *, void *) = _auditmemloc;static void _poolfault(void *, char *, ulong);void (*poolfault)(void *, char *, ulong) = _poolfault; /* non tracing *enum { Npadlong = 0, MallocOffset = 0, ReallocOffset = 0}; * */ /* tracing */enum { Npadlong = 2, MallocOffset = 0, ReallocOffset = 1}; enum { Monitor = 1}; void (*memmonitor)(int, ulong, ulong, ulong) = nil;#define MM(v,pc,base,size) if(!Monitor || memmonitor==nil){} else memmonitor((v),(pc),(base),(size)) #define CKLEAK 0int ckleak;#define ML(v, sz, pc) if(CKLEAK && ckleak && v){ if(sz) fprint(2, "%lux %lux %lux\n", (ulong)v, (ulong)sz, (ulong)pc); else fprint(2, "%lux\n", (ulong)v); } intmemusehigh(void){ return mainmem->cursize > mainmem->ressize || heapmem->cursize > heapmem->ressize || 0 && imagmem->cursize > imagmem->ressize;} intmemlow(void){ return heapmem->cursize > (heapmem->maxsize)/2;} intpoolsetsize(char *s, int size){ int i; for(i = 0; i < table.n; i++) { if(strcmp(table.pool[i].name, s) == 0) { table.pool[i].maxsize = size; table.pool[i].ressize = size-RESERVED; if(size < RESERVED) panic("not enough memory"); return 1; } } return 0;} voidpoolimmutable(void *v){ Bhdr *b; D2B(b, v); b->magic = MAGIC_I;} voidpoolmutable(void *v){ Bhdr *b; D2B(b, v); b->magic = MAGIC_A; ((Heap*)v)->color = mutator;} char*poolname(Pool *p){ return p->name;} Bhdr*poolchain(Pool *p){ return p->chain;} voidpooldel(Pool *p, Bhdr *t){ Bhdr *s, *f, *rp, *q; if(t->parent == nil && p->root != t) { t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->fwd != t) { f = t->fwd; s = t->parent; f->parent = s; if(s == nil) p->root = f; else { if(s->left == t) s->left = f; else s->right = f; } rp = t->left; f->left = rp; if(rp != nil) rp->parent = f; rp = t->right; f->right = rp; if(rp != nil) rp->parent = f; t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->left == nil) rp = t->right; else { if(t->right == nil) rp = t->left; else { f = t; rp = t->right; s = rp->left; while(s != nil) { f = rp; rp = s; s = rp->left; } if(f != t) { s = rp->right; f->left = s; if(s != nil) s->parent = f; s = t->right; rp->right = s; if(s != nil) s->parent = rp; } s = t->left; rp->left = s; s->parent = rp; } } q = t->parent; if(q == nil) p->root = rp; else { if(t == q->left) q->left = rp; else q->right = rp; } if(rp != nil) rp->parent = q;} voidpooladd(Pool *p, Bhdr *q){ int size; Bhdr *tp, *t; q->magic = MAGIC_F; q->left = nil; q->right = nil; q->parent = nil; q->fwd = q; q->prev = q; t = p->root; if(t == nil) { p->root = q; return; } size = q->size; tp = nil; while(t != nil) { if(size == t->size) { q->prev = t->prev; q->prev->fwd = q; q->fwd = t; t->prev = q; return; } tp = t; if(size < t->size) t = t->left; else t = t->right; } q->parent = tp; if(size < tp->size) tp->left = q; else tp->right = q;} static void*dopoolalloc(Pool *p, ulong asize, ulong pc){ Bhdr *q, *t; int alloc, ldr, ns, frag; int osize, size; if(asize >= 1024*1024*1024) /* for sanity and to avoid overflow */ return nil; size = asize; osize = size; size = (size + BHDRSIZE + p->quanta) & ~(p->quanta); lock(&p->l); p->nalloc++; t = p->root; q = nil; while(t) { if(t->size == size) { t = t->fwd; pooldel(p, t); t->magic = MAGIC_A; p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(t), size); return B2D(t); } if(size < t->size) { q = t; t = t->left; } else t = t->right; } if(q != nil) { pooldel(p, q); q->magic = MAGIC_A; frag = q->size - size; if(frag < (size>>2) && frag < 0x8000) { p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(q), size); return B2D(q); } /* Split */ ns = q->size - size; q->size = size; B2T(q)->hdr = q; t = B2NB(q); t->size = ns; B2T(t)->hdr = t; pooladd(p, t); p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(q), size); return B2D(q); } ns = p->chunk; if(size > ns) ns = size; ldr = p->quanta+1; alloc = ns+ldr+ldr; p->arenasize += alloc; if(p->arenasize > p->maxsize) { p->arenasize -= alloc; ns = p->maxsize-p->arenasize-ldr-ldr; ns &= ~p->quanta; if (ns < size) { if(poolcompact(p)) { unlock(&p->l); return poolalloc(p, osize); } unlock(&p->l); print("arena %s too large: size %d cursize %lud arenasize %lud maxsize %lud\n", p->name, size, p->cursize, p->arenasize, p->maxsize); return nil; } alloc = ns+ldr+ldr; p->arenasize += alloc; } p->nbrk++; t = (Bhdr *)sbrk(alloc); if(t == (void*)-1) { p->nbrk--; unlock(&p->l); return nil; } /* Double alignment */ t = (Bhdr *)(((ulong)t + 7) & ~7); if(p->chain != nil && (char*)t-(char*)B2LIMIT(p->chain)-ldr == 0){ /* can merge chains */ if(0)print("merging chains %p and %p in %s\n", p->chain, t, p->name); q = B2LIMIT(p->chain); q->magic = MAGIC_A; q->size = alloc; B2T(q)->hdr = q; t = B2NB(q); t->magic = MAGIC_E; p->chain->csize += alloc; p->cursize += alloc; unlock(&p->l); poolfree(p, B2D(q)); /* for backward merge */ return poolalloc(p, osize); } t->magic = MAGIC_E; /* Make a leader */ t->size = ldr; t->csize = ns+ldr; t->clink = p->chain; p->chain = t; B2T(t)->hdr = t; t = B2NB(t); t->magic = MAGIC_A; /* Make the block we are going to return */ t->size = size; B2T(t)->hdr = t; q = t; ns -= size; /* Free the rest */ if(ns > 0) { q = B2NB(t); q->size = ns; B2T(q)->hdr = q; pooladd(p, q); } B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */ p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(t), size); return B2D(t);} void *poolalloc(Pool *p, ulong asize){ Prog *prog; if(p->cursize > p->ressize && (prog = currun()) != nil && prog->flags&Prestricted) return nil; return dopoolalloc(p, asize, getcallerpc(&p));} voidpoolfree(Pool *p, void *v){ Bhdr *b, *c; extern Bhdr *ptr; D2B(b, v); if(p->monitor) MM(p->pnum|(1<<8), getcallerpc(&p), (ulong)v, b->size); lock(&p->l); p->nfree++; p->cursize -= b->size; c = B2NB(b); if(c->magic == MAGIC_F) { /* Join forward */ if(c == ptr) ptr = b; pooldel(p, c); c->magic = 0; b->size += c->size; B2T(b)->hdr = b; } c = B2PT(b)->hdr; if(c->magic == MAGIC_F) { /* Join backward */ if(b == ptr) ptr = c; pooldel(p, c); b->magic = 0; c->size += b->size; b = c; B2T(b)->hdr = b; } pooladd(p, b); unlock(&p->l);} void *poolrealloc(Pool *p, void *v, ulong size){ Bhdr *b; void *nv; int osize; if(size >= 1024*1024*1024) /* for sanity and to avoid overflow */ return nil; if(size == 0){ poolfree(p, v); return nil; } SET(osize); if(v != nil){ lock(&p->l); D2B(b, v); osize = b->size - BHDRSIZE; unlock(&p->l); if(osize >= size) return v; }Lines 1–500 of 1041. Load more
#include "dat.h" #include "fns.h" #include "interp.h" #include "error.h" enum { MAXPOOL = 4 }; #define left u.s.bhl #define right u.s.bhr #define fwd u.s.bhf #define prev u.s.bhv #define parent u.s.bhp #define RESERVED 512*1024 struct Pool { char* name; int pnum; ulong maxsize; int quanta; int chunk; int monitor; ulong ressize; /* restricted size */ ulong cursize; ulong arenasize; ulong hw; Lock l; Bhdr* root; Bhdr* chain; ulong nalloc; ulong nfree; int nbrk; int lastfree; void (*move)(void*, void*); }; void* initbrk(ulong); struct { int n; Pool pool[MAXPOOL]; /* Lock l; */ } table = { 3, { { "main", 0, 32*1024*1024, 63, 512*1024, 0, 31*1024*1024 }, { "heap", 1, 32*1024*1024, 63, 512*1024, 0, 31*1024*1024 }, { "image", 2, 32*1024*1024+256, 63, 4*1024*1024, 1, 31*1024*1024 }, } }; Pool* mainmem = &table.pool[0]; Pool* heapmem = &table.pool[1]; Pool* imagmem = &table.pool[2]; static void _auditmemloc(char *, void *); void (*auditmemloc)(char *, void *) = _auditmemloc; static void _poolfault(void *, char *, ulong); void (*poolfault)(void *, char *, ulong) = _poolfault; /* non tracing * enum { Npadlong = 0, MallocOffset = 0, ReallocOffset = 0 }; * */ /* tracing */ enum { Npadlong = 2, MallocOffset = 0, ReallocOffset = 1 }; enum { Monitor = 1 }; void (*memmonitor)(int, ulong, ulong, ulong) = nil; #define MM(v,pc,base,size) if(!Monitor || memmonitor==nil){} else memmonitor((v),(pc),(base),(size)) #define CKLEAK 0 int ckleak; #define ML(v, sz, pc) if(CKLEAK && ckleak && v){ if(sz) fprint(2, "%lux %lux %lux\n", (ulong)v, (ulong)sz, (ulong)pc); else fprint(2, "%lux\n", (ulong)v); } int memusehigh(void) { return mainmem->cursize > mainmem->ressize || heapmem->cursize > heapmem->ressize || 0 && imagmem->cursize > imagmem->ressize; } int memlow(void) { return heapmem->cursize > (heapmem->maxsize)/2; } int poolsetsize(char *s, int size) { int i; for(i = 0; i < table.n; i++) { if(strcmp(table.pool[i].name, s) == 0) { table.pool[i].maxsize = size; table.pool[i].ressize = size-RESERVED; if(size < RESERVED) panic("not enough memory"); return 1; } } return 0; } void poolimmutable(void *v) { Bhdr *b; D2B(b, v); b->magic = MAGIC_I; } void poolmutable(void *v) { Bhdr *b; D2B(b, v); b->magic = MAGIC_A; ((Heap*)v)->color = mutator; } char* poolname(Pool *p) { return p->name; } Bhdr* poolchain(Pool *p) { return p->chain; } void pooldel(Pool *p, Bhdr *t) { Bhdr *s, *f, *rp, *q; if(t->parent == nil && p->root != t) { t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->fwd != t) { f = t->fwd; s = t->parent; f->parent = s; if(s == nil) p->root = f; else { if(s->left == t) s->left = f; else s->right = f; } rp = t->left; f->left = rp; if(rp != nil) rp->parent = f; rp = t->right; f->right = rp; if(rp != nil) rp->parent = f; t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->left == nil) rp = t->right; else { if(t->right == nil) rp = t->left; else { f = t; rp = t->right; s = rp->left; while(s != nil) { f = rp; rp = s; s = rp->left; } if(f != t) { s = rp->right; f->left = s; if(s != nil) s->parent = f; s = t->right; rp->right = s; if(s != nil) s->parent = rp; } s = t->left; rp->left = s; s->parent = rp; } } q = t->parent; if(q == nil) p->root = rp; else { if(t == q->left) q->left = rp; else q->right = rp; } if(rp != nil) rp->parent = q; } void pooladd(Pool *p, Bhdr *q) { int size; Bhdr *tp, *t; q->magic = MAGIC_F; q->left = nil; q->right = nil; q->parent = nil; q->fwd = q; q->prev = q; t = p->root; if(t == nil) { p->root = q; return; } size = q->size; tp = nil; while(t != nil) { if(size == t->size) { q->prev = t->prev; q->prev->fwd = q; q->fwd = t; t->prev = q; return; } tp = t; if(size < t->size) t = t->left; else t = t->right; } q->parent = tp; if(size < tp->size) tp->left = q; else tp->right = q; } static void* dopoolalloc(Pool *p, ulong asize, ulong pc) { Bhdr *q, *t; int alloc, ldr, ns, frag; int osize, size; if(asize >= 1024*1024*1024) /* for sanity and to avoid overflow */ return nil; size = asize; osize = size; size = (size + BHDRSIZE + p->quanta) & ~(p->quanta); lock(&p->l); p->nalloc++; t = p->root; q = nil; while(t) { if(t->size == size) { t = t->fwd; pooldel(p, t); t->magic = MAGIC_A; p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(t), size); return B2D(t); } if(size < t->size) { q = t; t = t->left; } else t = t->right; } if(q != nil) { pooldel(p, q); q->magic = MAGIC_A; frag = q->size - size; if(frag < (size>>2) && frag < 0x8000) { p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(q), size); return B2D(q); } /* Split */ ns = q->size - size; q->size = size; B2T(q)->hdr = q; t = B2NB(q); t->size = ns; B2T(t)->hdr = t; pooladd(p, t); p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(q), size); return B2D(q); } ns = p->chunk; if(size > ns) ns = size; ldr = p->quanta+1; alloc = ns+ldr+ldr; p->arenasize += alloc; if(p->arenasize > p->maxsize) { p->arenasize -= alloc; ns = p->maxsize-p->arenasize-ldr-ldr; ns &= ~p->quanta; if (ns < size) { if(poolcompact(p)) { unlock(&p->l); return poolalloc(p, osize); } unlock(&p->l); print("arena %s too large: size %d cursize %lud arenasize %lud maxsize %lud\n", p->name, size, p->cursize, p->arenasize, p->maxsize); return nil; } alloc = ns+ldr+ldr; p->arenasize += alloc; } p->nbrk++; t = (Bhdr *)sbrk(alloc); if(t == (void*)-1) { p->nbrk--; unlock(&p->l); return nil; } /* Double alignment */ t = (Bhdr *)(((ulong)t + 7) & ~7); if(p->chain != nil && (char*)t-(char*)B2LIMIT(p->chain)-ldr == 0){ /* can merge chains */ if(0)print("merging chains %p and %p in %s\n", p->chain, t, p->name); q = B2LIMIT(p->chain); q->magic = MAGIC_A; q->size = alloc; B2T(q)->hdr = q; t = B2NB(q); t->magic = MAGIC_E; p->chain->csize += alloc; p->cursize += alloc; unlock(&p->l); poolfree(p, B2D(q)); /* for backward merge */ return poolalloc(p, osize); } t->magic = MAGIC_E; /* Make a leader */ t->size = ldr; t->csize = ns+ldr; t->clink = p->chain; p->chain = t; B2T(t)->hdr = t; t = B2NB(t); t->magic = MAGIC_A; /* Make the block we are going to return */ t->size = size; B2T(t)->hdr = t; q = t; ns -= size; /* Free the rest */ if(ns > 0) { q = B2NB(t); q->size = ns; B2T(q)->hdr = q; pooladd(p, q); } B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */ p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; unlock(&p->l); if(p->monitor) MM(p->pnum, pc, (ulong)B2D(t), size); return B2D(t); } void * poolalloc(Pool *p, ulong asize) { Prog *prog; if(p->cursize > p->ressize && (prog = currun()) != nil && prog->flags&Prestricted) return nil; return dopoolalloc(p, asize, getcallerpc(&p)); } void poolfree(Pool *p, void *v) { Bhdr *b, *c; extern Bhdr *ptr; D2B(b, v); if(p->monitor) MM(p->pnum|(1<<8), getcallerpc(&p), (ulong)v, b->size); lock(&p->l); p->nfree++; p->cursize -= b->size; c = B2NB(b); if(c->magic == MAGIC_F) { /* Join forward */ if(c == ptr) ptr = b; pooldel(p, c); c->magic = 0; b->size += c->size; B2T(b)->hdr = b; } c = B2PT(b)->hdr; if(c->magic == MAGIC_F) { /* Join backward */ if(b == ptr) ptr = c; pooldel(p, c); b->magic = 0; c->size += b->size; b = c; B2T(b)->hdr = b; } pooladd(p, b); unlock(&p->l); } void * poolrealloc(Pool *p, void *v, ulong size) { Bhdr *b; void *nv; int osize; if(size >= 1024*1024*1024) /* for sanity and to avoid overflow */ return nil; if(size == 0){ poolfree(p, v); return nil; } SET(osize); if(v != nil){ lock(&p->l); D2B(b, v); osize = b->size - BHDRSIZE; unlock(&p->l); if(osize >= size) return v; }