1041 lines · 18.1 KB · C
RawDownload
#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.