Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/alloc.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/alloc.c 1992/0618
## diff -e /dev/null /n/bootesdump/1992/0618/sys/src/9/port/alloc.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#define	nil	((void*)0)
#define datoff	((int)&((Xhdr*)0)->data)

enum
{
	Nhole	= 128,
	Magic	= 0xDeadBabe,
};

typedef struct Hole Hole;
typedef struct Xalloc Xalloc;
typedef struct Xhdr Xhdr;
struct Hole
{
	ulong	addr;
	ulong	size;
	ulong	top;
	Hole	*link;
};

struct Xhdr
{
	ulong	size;
	ulong	magix;
	char	data[1];
};

struct Xalloc
{
	Lock;
	Hole	hole[Nhole];
	Hole	*flist;
	Hole	*table;
};

Xalloc	xlists;

void
xinit(void)
{
	Hole *h, *eh;

	eh = &xlists.hole[Nhole-1];
	for(h = xlists.hole; h < eh; h++)
		h->link = h+1;

	xlists.flist = h;
}

void
xhole(ulong addr, ulong size)
{
	Hole *h, **l;

	lock(&xlists);
	l = &xlists.table;
	for(h = *l; h; h = h->link) {
		if(h->top == addr) {
			h->size += size;
			h->top = h->addr+h->size;
			unlock(&xlists);
			return;
		}
		if(h->addr > addr)
			break;
		l = &h->link;
	}

	if(xlists.flist == nil) {
		print("xfree: no free holes, leaked %d bytes\n", size);
		unlock(&xlists);
		return;
	}

	h = xlists.flist;
	xlists.flist = h->link;
	h->addr = addr;
	h->top = addr+size;
	h->size = size;
	h->link = *l;
	*l = h;
	unlock(&xlists);
}

void*
xalloc(ulong size)
{
	Hole *h, **l;
	Xhdr *p;

	size += sizeof(Xhdr);

	lock(&xlists);
	l = &xlists.table;
	for(h = *l; h; h = h->link) {
		if(h->size >= size) {
			p = (Xhdr*)h->addr;
			h->addr += size;
			h->size -= size;
			if(h->size == 0) {
				*l = h->link;
				h->link = xlists.flist;
				xlists.flist = h;
			}
			p->magix = Magic;
			p->size = size;
			unlock(&xlists);
			return p->data;
		}
		l = &h->link;
	}
	unlock(&xlists);
	return nil;
}

void
xfree(void *p)
{
	Xhdr *x;

	x = (Xhdr*)((ulong)p - datoff);
	if(x->magix != Magic)
		panic("xfree");

	xhole((ulong)x, x->size);
}

void
xsummary(void)
{
	int i;
	Hole *h;

	i = 0;
	for(h = xlists.flist; h; h = h->link)
		i++;

	print("%d holes free\n", i);
	i = 0;
	for(h = xlists.table; h; h = h->link) {
		print("%lux %lux %d\n", h->addr, h->top, h->size);
		i += h->size;
	}
	print("%d bytes free\n", i);
}
.
## diffname port/alloc.c 1992/0619
## diff -e /n/bootesdump/1992/0618/sys/src/9/port/alloc.c /n/bootesdump/1992/0619/sys/src/9/port/alloc.c
149a
}

void*
malloc(ulong size)
{
	int pow;
	Bucket *bp;

	for(pow = 1; pow < Maxpow; pow++)
		if(size <= (1<<pow))
			goto good;

	return nil;
good:
	/* Allocate off this list */
	lock(&arena);
	bp = arena.btab[pow];
	if(bp) {
		arena.btab[pow] = bp->next;
		unlock(&arena);

		if(bp->magic != 0)
			panic("malloc");

		bp->magic = Magic2n;

		memset(bp->data, 0,  size);
		return  bp->data;
	}
	unlock(&arena);
	size = sizeof(Bucket)+(1<<pow);
	bp = xalloc(size);
	if(bp == nil)
		return nil;

	bp->size = pow;
	bp->magic = Magic2n;
	return bp->data;
}

void*
smalloc(ulong size)
{
	void *p;

	p = malloc(size);
	if(p == nil)
		panic("smalloc should sleep");
	return p;
}

void
free(void *ptr)
{
	Bucket *bp, **l;

	bp = (Bucket*)((ulong)ptr - bdatoff);
	if(bp->magic != Magic2n)
		panic("free");

	bp->magic = 0;
	lock(&arena);
	l = &arena.btab[bp->size];
	bp->next = *l;
	*l = bp;
	unlock(&arena);
.
146c
		print("%.8lux %.8lux %d\n", h->addr, h->top, h->size);
.
133a
xhole(ulong addr, ulong size)
{
	ulong top;
	Hole *h, *c, **l;

	if(size == 0)
		return;

	top = addr + size;
	lock(&xlists);
	l = &xlists.table;
	for(h = *l; h; h = h->link) {
		if(h->top == addr) {
			h->size += size;
			h->top = h->addr+h->size;
			c = h->link;
			if(c && h->top == c->addr) {
				h->top += c->size;
				h->size += c->size;
				h->link = c->link;
				c->link = xlists.flist;
				xlists.flist = c;
			}
			unlock(&xlists);
			return;
		}
		if(h->addr > addr)
			break;
		l = &h->link;
	}
	if(h && top == h->addr) {
		h->addr -= size;
		h->size += size;
		unlock(&xlists);
		return;
	}

	if(xlists.flist == nil) {
		unlock(&xlists);
		print("xfree: no free holes, leaked %d bytes\n", size);
		return;
	}

	h = xlists.flist;
	xlists.flist = h->link;
	h->addr = addr;
	h->top = top;
	h->size = size;
	h->link = *l;
	*l = h;
	unlock(&xlists);
}

void
.
130c
	xhole(PADDR(x), x->size);
.
127c
	if(x->magix != Magichole)
.
110c
			p = KADDR(p);
			memset(p, 0, size);
			p->magix = Magichole;
.
96c
	size += BY2WD + sizeof(Xhdr);
	size &= ~(BY2WD-1);
.
94a
	Hole *h, **l;
.
93d
80,87c
	np0 = up;
	if(np0 > conf.npage0)
		np0 = conf.npage0;

	palloc.p0 = conf.base0;
	conf.base0 += np0*BY2PG;
	conf.npage0 -= np0;
	xhole(conf.base0, conf.npage0*BY2PG);

	palloc.np0 = np0;
	palloc.np1 = np1;
.
74,78c
	palloc.p1 = conf.base1;
	conf.base1 += np1*BY2PG;
	conf.npage1 -= np1;
	xhole(conf.base1, conf.npage1*BY2PG);
	up -= np1;
.
60,72c
	up = conf.upages;
	np1 = up;
	if(np1 > conf.npage1)
		np1 = conf.npage1;
.
55,58c
	ktop = PGROUND((ulong)end);
	ktop = PADDR(ktop);
	conf.npage0 -= ktop/BY2PG;
	conf.base0 += ktop;
.
52,53c
	xlists.flist = xlists.hole;
.
46a
	int up, np0, np1;
.
45a
	ulong ktop;
.
42a
struct Arena
{
	Lock;
	Bucket	*btab[Maxpow];	
};

static Arena	arena;
static Xalloc	xlists;

void*
ialloc(ulong size, int align)
{
	ulong p;

	if(align) {
		size += BY2PG;
		p = (ulong)xalloc(size);
		p += BY2PG;
		p &= ~(BY2PG-1);
		return (void*)p;
	}

	return xalloc(size);
}

void*
iallocspan(ulong size, int quanta, ulong span)
{
	return ialloc(size, quanta);
}

.
41c
struct Bucket
{
	int	size;
	int	magic;
	Bucket	*next;
	char	data[1];
};
.
17a
typedef struct Bucket Bucket;
typedef struct Arena Arena;

.
11,12c
	Maxpow		= 16,
	Nhole		= 128,
	Magichole	= 0xDeadBabe,
	Magic2n		= 0xBadC0c0a,
.
8a
#define	nil		((void*)0)
#define datoff		((ulong)&((Xhdr*)0)->data)
#define bdatoff		((ulong)&((Bucket*)0)->data)

.
6,7d
## diffname port/alloc.c 1992/0620
## diff -e /n/bootesdump/1992/0619/sys/src/9/port/alloc.c /n/bootesdump/1992/0620/sys/src/9/port/alloc.c
311a
}

void
xsummary(void)
{
	Hole *h;
	Bucket *k;
	int i, nfree;

	i = 0;
	for(h = xlists.flist; h; h = h->link)
		i++;

	print("%d holes free\n", i);
	i = 0;
	for(h = xlists.table; h; h = h->link) {
		print("%.8lux %.8lux %d\n", h->addr, h->top, h->size);
		i += h->size;
	}
	print("%d bytes free\n", i);
	for(i = 3; i < Maxpow; i++) {
		if(arena.btab[i] == 0 && arena.nbuck[i] == 0)
			continue;
		nfree = 0;
		for(k = arena.btab[i]; k; k = k->next)
			nfree++;
		print("%8d %4d %4d\n", 1<<i, arena.nbuck[i], nfree);
	}
.
274a
	arena.nbuck[pow]++;
.
254c
	for(pow = 3; pow < Maxpow; pow++)
.
229,247d
59c
	Bucket	*btab[Maxpow];
	int	nbuck[Maxpow];
.
16c
	Magic2n		= 0xFeedBeef,
.
## diffname port/alloc.c 1992/0621
## diff -e /n/bootesdump/1992/0620/sys/src/9/port/alloc.c /n/bootesdump/1992/0621/sys/src/9/port/alloc.c
127a
}

/*
 * NB. spanalloc memory will cause a panic if free'd
 */
void*
xspanalloc(ulong size, int align, ulong span)
{
	int i, j;
	ulong a, p;
	ulong ptr[Spanlist];

	span = ~(span-1);
	for(i = 0; i < Spanlist; i++) {
		p = (ulong)xalloc(size+align);
		if(p == 0)
			panic("xspanalloc: size %d align %d span %d", size, align, span);

		a = p+align;
		a &= ~(align-1);
		if((a&span) == ((a+size)&span)) {
			for(j = 0; j < i; j++)
				xfree((void*)ptr[j]);

			return (void*)a;
		}
		ptr[i] = p;
	}
	panic("xspanalloc: spanlist");		
	return 0;
.
82,87d
78,79c
	return xalloc(size);;
.
16a
	Spanlist	= 64,
.
8,9c
#define datoff		((ulong)((Xhdr*)0)->data)
#define bdatoff		((ulong)((Bucket*)0)->data)
.
6a
/*
 * Plan 9 has two kernel allocators, the x... routines provide a first
 * fit hole allocator which should be used for permanent or large structures.
 * Routines are provided to allocate aligned memory which does not cross
 * arbitrary 2^n boundaries. A second allocator malloc, smalloc, free is
 * a 2n bucket allocator which steals from the x routines. This should
 * be used for small frequently used structures.
 */

.
## diffname port/alloc.c 1992/0622
## diff -e /n/bootesdump/1992/0621/sys/src/9/port/alloc.c /n/bootesdump/1992/0622/sys/src/9/port/alloc.c
309a
	}
.
308c
	if(p == nil) {
		print("asking for %d\n", size);
		xsummary();
.
76,90d
## diffname port/alloc.c 1992/0623
## diff -e /n/bootesdump/1992/0622/sys/src/9/port/alloc.c /n/bootesdump/1992/0623/sys/src/9/port/alloc.c
298a
}

int
msize(void *ptr)
{
	Bucket *bp;

	bp = (Bucket*)((ulong)ptr - bdatoff);
	if(bp->magic != Magic2n)
		panic("msize");
	return 1<<bp->size;
.
173d
168a
			unlock(&xlists);
.
## diffname port/alloc.c 1992/0625
## diff -e /n/bootesdump/1992/0623/sys/src/9/port/alloc.c /n/bootesdump/1992/0625/sys/src/9/port/alloc.c
326a
	if(arena.r.p)
		wakeup(&arena.r);
.
292,296c
	for(;;) {
		p = malloc(size);
		if(p != nil)
			return p;
		s = u->p->psstate;
		u->p->psstate = "Malloc";
		qlock(&arena.rq);
		while(waserror())
			;
		sleep(&arena.r, return0, nil);
		poperror();
		qunlock(&arena.rq);
		u->p->psstate = s;
.
289a
	char *s;
.
115a
	/* Save the bounds of kernel alloc memory for kernel mmu mapping (NeXT) */
	conf.base0 = (ulong)KADDR(conf.base0);
	conf.base1 = (ulong)KADDR(conf.base1);
	conf.npage0 = (ulong)KADDR(conf.npage0);
	conf.npage1 = (ulong)KADDR(conf.npage1);
.
112a
	conf.npage0 = conf.base0+(conf.npage0*BY2PG);
.
102a
	conf.npage1 = conf.base1+(conf.npage1*BY2PG);
.
70a
	QLock	rq;
	Rendez	r;
.
## diffname port/alloc.c 1992/0707
## diff -e /n/bootesdump/1992/0625/sys/src/9/port/alloc.c /n/bootesdump/1992/0707/sys/src/9/port/alloc.c
316c
	pexit(Enomem, 1);
	return 0;
.
302c
	for(attempt = 0; attempt < 1000; attempt++) {
.
300a
	int attempt;
.
263c
	for(pow = 3; pow <= Maxpow; pow++)
.
22c
	Maxpow		= 18,
.
5a
#include	"error.h"
.
## diffname port/alloc.c 1992/0708
## diff -e /n/bootesdump/1992/0707/sys/src/9/port/alloc.c /n/bootesdump/1992/0708/sys/src/9/port/alloc.c
153a
	USED(sinc);
.
152c
		xfree((void*)p);
		ptr[i] = (ulong)xalloc(sinc);
.
148c
				if(ptr[j])
					xfree((void*)ptr[j]);
.
142c
			panic("xspanalloc: size %d align %d span %lux", size, align, span);
.
137a
	sinc = span/8;
.
135c
	ulong a, p, sinc;
.
## diffname port/alloc.c 1992/0715
## diff -e /n/bootesdump/1992/0708/sys/src/9/port/alloc.c /n/bootesdump/1992/0715/sys/src/9/port/alloc.c
91,95d
82d
## diffname port/alloc.c 1992/0720
## diff -e /n/bootesdump/1992/0715/sys/src/9/port/alloc.c /n/bootesdump/1992/0720/sys/src/9/port/alloc.c
286,288c
	size += 3;
	size &= ~3;

	if(pow < CUTOFF) {
		n = (CUTOFF-pow)+2;
		bp = xalloc(size*n);
		if(bp == nil)
			return nil;

		next = (ulong)bp+size;
		nbp = (Bucket*)next;
		lock(&arena);
		arena.btab[pow] = nbp;
		arena.nbuck[pow] += n;
		for(n -= 2; n; n--) {
			next = (ulong)nbp+size;
			nbp->next = (Bucket*)next;
			nbp->size = pow;
			nbp = nbp->next;
		}
		nbp->size = pow;
		unlock(&arena);
	}
	else {
		bp = xalloc(size);
		if(bp == nil)
			return nil;
	}
.
284a

.
283d
259,260c
	ulong next;
	int pow, n;
	Bucket *bp, *nbp;
.
137c
			panic("xspanalloc: %d %d %lux", size, align, span);
.
23a
	CUTOFF		= 12,
.
## diffname port/alloc.c 1992/0726
## diff -e /n/bootesdump/1992/0720/sys/src/9/port/alloc.c /n/bootesdump/1992/0726/sys/src/9/port/alloc.c
116c
	/* Save the bounds of kernel alloc memory for kernel mmu mapping */
.
## diffname port/alloc.c 1992/0729
## diff -e /n/bootesdump/1992/0726/sys/src/9/port/alloc.c /n/bootesdump/1992/0729/sys/src/9/port/alloc.c
153c
	xsummary();
	panic("xspanalloc: %d %d %lux\n", size, align, span);	
.
138c
			break;
.
133c
	sinc = size/8;
.
## diffname port/alloc.c 1992/0912
## diff -e /n/bootesdump/1992/0729/sys/src/9/port/alloc.c /n/bootesdump/1992/0912/sys/src/9/port/alloc.c
403a
	print("%d bytes in pool\n", nused);
.
398a
		nused += arena.nbuck[i]*(1<<i);
.
395a
	nused = 0;
.
383c
	int i, nfree, nused;
.
## diffname port/alloc.c 1992/0913
## diff -e /n/bootesdump/1992/0912/sys/src/9/port/alloc.c /n/bootesdump/1992/0913/sys/src/9/port/alloc.c
315a

		arena.nbuck[pow]++;
.
7a

.
## diffname port/alloc.c 1993/0116
## diff -e /n/bootesdump/1992/0913/sys/src/9/port/alloc.c /n/bootesdump/1993/0116/sys/src/9/port/alloc.c
372,373d
370d
367a
	l = &arena.btab[bp->size];

	lock(&arena);
.
280c
			panic("malloc %lux", bp->magic);
.
## diffname port/alloc.c 1993/0120
## diff -e /n/bootesdump/1993/0116/sys/src/9/port/alloc.c /n/bootesdump/1993/0120/sys/src/9/port/alloc.c
318a
		unlock(&arena);
.
317a
		lock(&arena);
.
310d
308c
			nbp->next = arena.btab[pow];
			arena.btab[pow] = nbp;
.
306c
			nbp = (Bucket*)next;
.
304c
		while(--n) {
.
302d
299,300c
		nbp = bp;
.
266c
	for(pow = 3; pow < Maxpow; pow++)
.
## diffname port/alloc.c 1993/0121
## diff -e /n/bootesdump/1993/0120/sys/src/9/port/alloc.c /n/bootesdump/1993/0121/sys/src/9/port/alloc.c
284c
		memset(bp->data, 0, size);
.
279,280c
		if(bp->magic != 0 || bp->size != pow)
			panic("malloc bp %lux magic %lux size %d next %lux pow %d", bp,
				bp->magic, bp->size, bp->next, pow);
.
## diffname port/alloc.c 1993/0205
## diff -e /n/bootesdump/1993/0121/sys/src/9/port/alloc.c /n/bootesdump/1993/0205/sys/src/9/port/alloc.c
319d
317d
283a
		unlock(&arena);
.
282c
		}
.
277,279c
		if(bp->magic != 0 || bp->size != pow){
			unlock(&arena);
.
## diffname port/alloc.c 1993/0501
## diff -e /n/bootesdump/1993/0205/sys/src/9/port/alloc.c /n/fornaxdump/1993/0501/sys/src/brazil/port/alloc.c
372a
	lock(&arena);
	l = &arena.btab[bp->size];
.
371a

.
367,369d
344c
		up->psstate = s;
.
336,337c
		s = up->psstate;
		up->psstate = "Malloc";
.
309a
		nbp->size = pow;
.
307,308c
			nbp = nbp->next;
.
305c
			nbp->next = (Bucket*)next;
.
303c
		for(n -= 2; n; n--) {
.
301a
		arena.btab[pow] = nbp;
.
300c
		next = (ulong)bp+size;
		nbp = (Bucket*)next;
.
285c
		if(bp->magic != 0)
			panic("malloc");

		bp->magic = Magic2n;

		memset(bp->data, 0,  size);
.
277,282d
266c
	for(pow = 3; pow <= Maxpow; pow++)
.
## diffname port/alloc.c 1993/0515
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/0515/sys/src/brazil/port/alloc.c
109,110c
	palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG;
.
98,99c
	palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG;
.
## diffname port/alloc.c 1993/1121
## diff -e /n/fornaxdump/1993/0515/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/1121/sys/src/brazil/port/alloc.c
320a
bp->pc = pc;
.
281c
bp->pc = pc;
.
262a
ulong pc;
pc = getcallerpc(0);
.
65a
	ulong	pc;
.
## diffname port/alloc.c 1993/1125
## diff -e /n/fornaxdump/1993/1121/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/1125/sys/src/brazil/port/alloc.c
338a
		}
.
337c
		if(p != nil) {
			bp = (Bucket*)((ulong)p - bdatoff);
			bp->pc = getcallerpc(((uchar*)&size) - sizeof(size));
.
333a
	Bucket *bp;
.
324c
	bp->pc = getcallerpc(((uchar*)&size) - sizeof(size));
.
284c
		bp->pc = getcallerpc(((uchar*)&size) - sizeof(size));
.
264,265d
## diffname port/alloc.c 1993/1231
## diff -e /n/fornaxdump/1993/1125/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/1231/sys/src/brazil/port/alloc.c
152,155c
	else
		v = a;

	if(align > 1)
		v = (v + align) & ~(align-1);

	return (void*)v;
.
140,150c
	if(span > 2) {
		v = (a + span) & ~(span-1);
		t = v - a;
		if(t > 0)
			xhole(PADDR(a), t);
		t = a + span - v;
		if(t > 0)
			xhole(PADDR(v+size+align), t);
.
133,138c
	a = (ulong)xalloc(size+align+span);
	if(a == 0)
		panic("xspanalloc: %d %d %lux\n", size, align, span);
.
129,131c
	ulong a, v, t;
.
## diffname port/alloc.c 1994/0208
## diff -e /n/fornaxdump/1993/1231/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0208/sys/src/brazil/port/alloc.c
120a

	/* setup initial memory allocations for interrupt time */
	qinit();
.
## diffname port/alloc.c 1994/0222
## diff -e /n/fornaxdump/1994/0208/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0222/sys/src/brazil/port/alloc.c
371c
		panic("free %lux %lux", bp->magic, bp->pc);
.
277c
			panic("malloc %lux %lux", bp->magic, bp->pc);
.
## diffname port/alloc.c 1994/0223
## diff -e /n/fornaxdump/1994/0222/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0223/sys/src/brazil/port/alloc.c
196,197c
	if(x->magix != Magichole) {
		uchar *a;
		int i;
		a = (uchar*)x;
		for(i = 0; i < 32; i++)
			print("#%lux ", *a++);
		panic("xfree(0x%lux) 0x%lux!=0x%lux", p, Magichole, x->magix);
	}
.
189a
void*
xalloc(ulong size)
{
	return xallocz(size, 1);
}

.
179c
			if(zero)
				memset(p, 0, size);
.
157c
xallocz(ulong size, int zero)
.
## diffname port/alloc.c 1994/0224
## diff -e /n/fornaxdump/1994/0223/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0224/sys/src/brazil/port/alloc.c
211d
204,208c
		xsummary();
.
## diffname port/alloc.c 1994/0306
## diff -e /n/fornaxdump/1994/0224/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0306/sys/src/brazil/port/alloc.c
295,296c
	size += BY2V;
	size &= ~(BY2V-1);
.
162,163c
	size += BY2V + sizeof(Xhdr);
	size &= ~(BY2V-1);
.
## diffname port/alloc.c 1994/0322
## diff -e /n/fornaxdump/1994/0306/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0322/sys/src/brazil/port/alloc.c
386c
	iunlock(&arena);
.
382c
	ilock(&arena);
.
346d
342,344c
		if(p != nil)
.
338d
328c

.
316c
		iunlock(&arena);
.
306c
		ilock(&arena);
.
292c
	iunlock(&arena);
.
288,289c

		if(zero)
			memset(bp->data, 0,  size);
.
282c
		iunlock(&arena);
.
278c
	ilock(&arena);
.
265c
mallocz(ulong size, int zero)
.
261c
	iunlock(&xlists);
.
249c
		iunlock(&xlists);
.
244c
		iunlock(&xlists);
.
234c
			iunlock(&xlists);
.
220c
	ilock(&xlists);
.
191,196d
187c
	iunlock(&xlists);
.
177c
			iunlock(&xlists);
.
165c
	ilock(&xlists);
.
121,123d
## diffname port/alloc.c 1994/0812
## diff -e /n/fornaxdump/1994/0322/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0812/sys/src/brazil/port/alloc.c
324a
malloc(ulong size)
{
	return mallocz(size, 1);
}

void*
.
## diffname port/alloc.c 1995/0616
## diff -e /n/fornaxdump/1994/0812/sys/src/brazil/port/alloc.c /n/fornaxdump/1995/0616/sys/src/brazil/port/alloc.c
105c
	np0 = upages;
.
103c
	upages -= np1;
.
94,95c
	upages = conf.upages;
	np1 = upages;
.
86c
	int upages, np0, np1;
.
## diffname port/alloc.c 1996/0217
## diff -e /n/fornaxdump/1995/0616/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/0217/sys/src/brazil/port/alloc.c
18d
## diffname port/alloc.c 1996/0305
## diff -e /n/fornaxdump/1996/0217/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/0305/sys/src/brazil/port/alloc.c
266a

.
## diffname port/alloc.c 1996/0324
## diff -e /n/fornaxdump/1996/0305/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/0324/sys/src/brazil/port/alloc.c
23c
	Maxpow		= 19,
.
## diffname port/alloc.c 1996/1120
## diff -e /n/fornaxdump/1996/0324/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/1120/sys/src/brazil/port/alloc.c
373c
		panic("free %lux %lux %lux", bp->magic, bp->pc, getcallerpc(ptr));
.
307d
301,305c
		l = &arena.btab[pow];
		/* add all but the last to the free list */
		while(--n){
			bp->size = pow;
			bp->next = *l;
			*l = bp;
			bp = (Bucket*)((ulong)bp+size);
.
299d
296,297d
259c
	Bucket *bp, **l;
.
257d
## diffname port/alloc.c 1997/1101
## diff -e /n/fornaxdump/1996/1120/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1101/sys/src/brazil/port/alloc.c
410c

	return compacted;
.
399,408c
}

int
poolcompact(Pool *pool)
{
	Bhdr *base, *limit, *ptr, *end, *next;
	int compacted, recov, nb;

	if(pool->move == nil || pool->lastfree == pool->nfree)
		return 0;

	pool->lastfree = pool->nfree;

	base = pool->chain;
	ptr = B2NB(base);	/* First Block in arena has clink */
	limit = B2LIMIT(base);
	compacted = 0;

	pool->root = nil;
	end = ptr;
	recov = 0;
	while(base != nil) {
		next = B2NB(ptr);
		if(ptr->magic == MAGIC_A) {
			if(ptr != end) {
				memmove(end, ptr, ptr->size);
				pool->move(B2D(ptr), B2D(end));
				recov = (uchar*)ptr - (uchar*)end;
				compacted = 1;
			}
			end = B2NB(end);
		}
		if(next >= limit) {
			nb = (uchar*)limit - (uchar*)end;
			//print("recovered %d bytes\n", recov);
			//print("%d bytes at end\n", nb);
			USED(recov);
			if(nb > 0){
				if(nb < pool->quanta+1)
					panic("poolcompact: leftover too small\n");
				end->size = nb;
				pooladd(pool, end);
			}
			base = base->clink;
			if(base == nil)
				break;
			ptr = B2NB(base);
			end = ptr;	/* could do better by copying between chains */
			limit = B2LIMIT(base);
			recov = 0;
		} else
			ptr = next;
.
393,397c
	for(i=0; i<table.n; i++){
		p = &table.pool[i];
		if(strcmp(name, p->name) == 0){
			if(maxsize)
				p->maxsize = maxsize;
			if(quanta)
				p->quanta = quanta;
			if(chunk)
				p->chunk = chunk;
			return;
		}
.
389,391c
void
poolsetparam(char *name, ulong maxsize, int quanta, int chunk)
{
	Pool *p;
	int i;
.
385,387c
	p->move = move;
}
.
383c
poolsetcompact(Pool *p, void (*move)(void*, void*))
.
380a
*/
.
372,379c
	while(base != nil) {
		print("\tbase #%.8lux ptr #%.8lux", base, ptr);
		if(ptr->magic == MAGIC_A)
			print("\tA%.5d\n", ptr->size);
		else if(ptr->magic == MAGIC_E)
			print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize);
		else
			print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n",
				ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
		ptr = B2NB(ptr);
		if(ptr >= limit) {
			print("link to #%.8lux\n", base->clink);
			base = base->clink;
			if(base == nil)
				break;
			ptr = base;
			limit = B2LIMIT(base);
		}
	}
	return;
.
368,370c
	b = p->chain;
	if(b == nil)
		return;
	base = b;
	ptr = b;
	limit = B2LIMIT(b);
.
366c
	Bhdr *b, *base, *limit, *ptr;
.
364c
pooldump(Pool *p)
.
362a
/*
.
357,360c
	for(i = 0; i < table.n; i++)
		print("Arena: %s cursize=%d; maxsize=%d\n", table.pool[i].name, table.pool[i].cursize, table.pool[i].maxsize);
.
355c
	int i;
.
352,353c
void
poolsummary(void)
.
350a
*/
.
348,349d
334,346c
	if(b == nil)
		return;

	print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n",
		b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
	d++;
	for(t = b->fwd; t != b; t = t->fwd)
		print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
	pooldump(b->left, d, 'l');
	pooldump(b->right, d, 'r');
}


void
poolshow(void)
{
	int i;

	for(i = 0; i < table.n; i++) {
		print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
		pooldump(table.pool[i].root, 0, 'R');
.
330,332c
	Bhdr *t;
.
327,328c
/*
void
pooldump(Bhdr *b, int d, int c)
.
324c
	return malloc(n*szelem);
.
322c
calloc(ulong n, ulong szelem)
.
318c
	D2B(b, v);
	return b->size - BHDRSIZE;
.
315,316c
int
msize(void *v)
{
	Bhdr *b;
.
313a
	return nv;
}
.
312c
	osize = b->size - BHDRSIZE;
	if(osize >= size)
		return v;

	nv = poolalloc(mainmem, size);
	if(nv != nil) {
		memmove(nv, v, osize);
		free(v);
.
295,310c
	D2B(b, v);
.
289,293c
	if(v == nil)
		return malloc(size);
.
285,287c
void*
realloc(void *v, ulong size)
{
	Bhdr *b;
	void *nv;
	int osize;
.
283c
}
.
279,281c
void
free(void *v)
{
	Bhdr *b;

	if(v != nil) {
		D2B(b, v);
		poolfree(mainmem, v);
.
277c
	v = poolalloc(mainmem, size);
	if(clr && v != nil)
		memset(v, 0, size);
	return v;
}
.
274,275c
void*
mallocz(ulong size, int clr)
{
	void *v;
.
267,272c
	for(;;) {
		v = poolalloc(mainmem, size);
		if(v != nil)
			break;
		tsleep(&up->sleep, return0, 0, 100);
	}
	memset(v, 0, size);
	return v;
}
.
264,265c
void*
smalloc(ulong size)
{
	void *v;
.
260,262c
	v = poolalloc(mainmem, size);
	if(v != nil)
		memset(v, 0, size);
	return v;
}
.
257,258c
	void *v;
.
255c
malloc(ulong size)
.
243,251c
	return n;
.
238,241d
227,236d
224,225c
			else
				n = 0;
.
209,222c
		if(signed_off > 0) {
			signed_off -= n;
			if(signed_off < 0) {
				memmove(va, va+n+signed_off, -signed_off);
				n = -signed_off;
.
206,207c
	n = 0;
	signed_off = offset;
	for(i = 0; i < table.n; i++) {
		p = &table.pool[i];
		n += snprint(va+n, count-n, "%11d %11d %11d %11d %11d %11d %s\n",
			p->cursize,
			p->maxsize,
			p->hw,
			p->nalloc,
			p->nfree,
			p->nbrk,
			p->name);
.
203,204c
	Pool *p;
	int n, i, signed_off;
.
200,201c
int
poolread(char *va, int count, ulong offset)
.
197c

	c = B2PT(b)->hdr;
	if(c->magic == MAGIC_F) {	/* Join backward */
		pooldel(p, c);
		b->magic = 0;
		c->size += b->size;
		b = c;
		B2T(b)->hdr = b;
	}

	pooladd(p, b);
	iunlock(&p->l);
.
192,195c
	D2B(b, v);

	ilock(&p->l);
	p->nfree++;
	p->cursize -= b->size;

	c = B2NB(b);
	if(c->magic == MAGIC_F) {	/* Join forward */
		pooldel(p, c);
		c->magic = 0;
		b->size += c->size;
		B2T(b)->hdr = b;
.
190c
	Bhdr *b, *c;
.
188c
poolfree(Pool *p, void *v)
.
183,184c

	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;
	iunlock(&p->l);
	return B2D(t);
.
161,181c
	p->nbrk++;
	t = xalloc(alloc);
	if(t == nil) {
		iunlock(&p->l);
		return nil;
.
158,159c
		iunlock(&p->l);
		print("arena too large: size %d cursize %d arenasize %d maxsize %d\n",
			 size, p->cursize, p->arenasize, p->maxsize);
		return nil;
	}
.
152,156c
		if(poolcompact(p)) {
			iunlock(&p->l);
			return poolalloc(p, size);
		}
.
149,150c
	alloc = ns+ldr+sizeof(t->magic);
	p->arenasize += alloc;
	if(p->arenasize > p->maxsize) {
		p->arenasize -= alloc;
.
146,147c
	ns = p->chunk;
	if(size > ns)
		ns = size;
	ldr = p->quanta+1;
.
143,144c
	if(q != nil) {
		pooldel(p, q);
		q->magic = MAGIC_A;
		frag = q->size - size;
		if(frag < (size>>2)) {
			p->cursize += q->size;
			if(p->cursize > p->hw)
				p->hw = p->cursize;
			iunlock(&p->l);
			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;
		iunlock(&p->l);
		return B2D(q);
	}
.
134,141c
	ilock(&p->l);
	p->nalloc++;

	t = p->root;
	q = nil;
	while(t) {
		if(t->size == size) {
			pooldel(p, t);
			t->magic = MAGIC_A;
			p->cursize += t->size;
			if(p->cursize > p->hw)
				p->hw = p->cursize;
			iunlock(&p->l);
			return B2D(t);
		}
		if(size < t->size) {
			q = t;
			t = t->left;
		}
		else
			t = t->right;
.
130,132c
	size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
.
128c
	Bhdr *q, *t;
	int alloc, ldr, ns, frag;
.
126c
poolalloc(Pool *p, int size)
.
122,124d
108,119c
	q->parent = tp;
	if(size < tp->size)
		tp->left = q;
	else
		tp->right = q;
.
104,106c
	tp = nil;
	while(t != nil) {
		if(size == t->size) {
			q->fwd = t->fwd;
			q->fwd->prev = q;
			q->prev = t;
			t->fwd = q;
			return;
		}
		tp = t;
		if(size < t->size)
			t = t->left;
		else
			t = t->right;
	}
.
98,102c
	size = q->size;
.
93,96c
	t = p->root;
	if(t == nil) {
		p->root = q;
		return;
	}
.
91c
	q->left = nil;
	q->right = nil;
	q->parent = nil;
	q->fwd = q;
	q->prev = q;
.
87,89c
	q->magic = MAGIC_F;
.
84,85c
	int size;
	Bhdr *tp, *t;
.
82c
pooladd(Pool *p, Bhdr *q)
.
80a
	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;
}

.
78,79c
	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;
	}
.
71,76c
	Bhdr *s, *f, *rp, *q;
.
69c
void
pooldel(Pool *p, Bhdr *t)
.
62,67c
	return p->chain;
}
.
60c
Bhdr*
poolchain(Pool *p)
.
52,58c
int	poolcompact(Pool*);
.
45,50c
Pool*	mainmem = &table.pool[0];
Pool*	imagmem = &table.pool[1];
.
39,42c
	int	n;
	Pool	pool[MAXPOOL];
	Lock	l;
} table = {
	2,
	{
		{ "Main",	 4*1024*1024, 31,  128*1024 },
		{ "Image",	 8*1024*1024, 31, 2*1024*1024 },
	}
.
31,37c
struct
.
23,28c
	char*	name;
	ulong	maxsize;
	int	quanta;
	int	chunk;
	ulong	cursize;
	ulong	arenasize;
	ulong	hw;
	Lock	l;
	Bhdr*	root;
	Bhdr*	chain;
	int	nalloc;
	int	nfree;
	int	nbrk;
	int	lastfree;
	void	(*move)(void*, void*);
.
9,21c
struct Pool
.
7a
#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
.
3a
#include	"pool.h"
.
## diffname port/alloc.c 1997/1105
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1105/sys/src/brazil/port/alloc.c
603a

int
recur(Bhdr *t)
{
	if(t == 0)
		return 1;
	if(((ulong)t) < 0x80000000)
		return 0;
	if(((ulong)t) > 0x90000000)
		return 0;
	return recur(t->right) && recur(t->left);
}

int
poolok(void)
{
	return recur(mainmem->root);
}
.
## diffname port/alloc.c 1997/1108
## diff -e /n/emeliedump/1997/1105/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1108/sys/src/brazil/port/alloc.c
43c
		{ "Image",	 16*1024*1024, 31, 2*1024*1024 },
.
## diffname port/alloc.c 1997/1202
## diff -e /n/emeliedump/1997/1108/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1202/sys/src/brazil/port/alloc.c
188a
	if(size < 0 || size >= 1024*1024*1024)	/* for sanity and to avoid overflow */
		return nil;
.
## diffname port/alloc.c 1997/1208
## diff -e /n/emeliedump/1997/1202/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1208/sys/src/brazil/port/alloc.c
622c
	if(x & 1)
		return recur(mainmem->root);
	return recur(imagmem->root);
.
620c
poolok(int x)
.
## diffname port/alloc.c 1998/0128
## diff -e /n/emeliedump/1997/1208/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0128/sys/src/brazil/port/alloc.c
257,258c
		print("%s arena too large: size %d cursize %d arenasize %d maxsize %d\n",
			 p->name, size, p->cursize, p->arenasize, p->maxsize);
.
## diffname port/alloc.c 1998/0221
## diff -e /n/emeliedump/1998/0128/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0221/sys/src/brazil/port/alloc.c
618,625d
## diffname port/alloc.c 1998/0512
## diff -e /n/emeliedump/1998/0221/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0512/sys/src/brazil/port/alloc.c
233c
		pooladd(p, t);
.
99c
		if(t->right == nil)
.
90c

.
81c

.
68c

.
## diffname port/alloc.c 1998/0825
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0825/sys/src/brazil/port/alloc.c
487c
		print("Arena: %s cursize=%lud; maxsize=%lud\n",
			table.pool[i].name,
			table.pool[i].cursize,
			table.pool[i].maxsize);
.
340c
		n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n",
.
257c
		print("%s arena too large: size %d cursize %lud arenasize %lud maxsize %lud\n",
.
## diffname port/alloc.c 1998/0916
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0916/sys/src/brazil/port/alloc.c
489a
			table.pool[i].arenasize,
.
487c
		print("Arena: %s cursize=%lud; arenasize=%lud; maxsize=%lud\n",
.
## diffname port/alloc.c 1999/0125
## diff -e /n/emeliedump/1998/0916/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0125/sys/src/brazil/port/alloc.c
550a
			if(move != nil)
				p->move = move;
.
549c
			if(chunk != 0)
.
547c
			if(quanta != 0)
.
545c
			if(maxsize != 0)
.
533,538d
531c
poolsetparam(char *name, ulong maxsize, int quanta, int chunk, void (*move)(void*, void*))
.
## diffname port/alloc.c 1999/0209
## diff -e /n/emeliedump/1999/0125/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0209/sys/src/brazil/port/alloc.c
184c
poolalloc(Pool *p, long size)
.
## diffname port/alloc.c 1999/0211
## diff -e /n/emeliedump/1999/0209/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0211/sys/src/brazil/port/alloc.c
257c
		print("%s arena too large: size %ld cursize %lud arenasize %lud maxsize %lud\n",
.
## diffname port/alloc.c 1999/0501
## diff -e /n/emeliedump/1999/0211/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0501/sys/src/brazil/port/alloc.c
431a
{
Bhdr *h;
D2B(h, nv);
B2T(h)->pad = getcallerpc(&size);
}
.
396a
{
Bhdr *h;
D2B(h, v);
B2T(h)->pad = getcallerpc(&size);
}
.
385a
{
Bhdr *h;
D2B(h, v);
B2T(h)->pad = getcallerpc(&size);
}
.
370a
{
Bhdr *h;
D2B(h, v);
B2T(h)->pad = getcallerpc(&size);
}
.
## diffname port/alloc.c 1999/0511
## diff -e /n/emeliedump/1999/0501/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0511/sys/src/brazil/port/alloc.c
410a
		memset(v, 0, size);
.
406d
## diffname port/alloc.c 1999/0526
## diff -e /n/emeliedump/1999/0511/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0526/sys/src/brazil/port/alloc.c
410d
406c
		memset(v, 0, size);
if(v != nil){
.
371c
if(v != nil){
.
## diffname port/alloc.c 1999/0527
## diff -e /n/emeliedump/1999/0526/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0527/sys/src/brazil/port/alloc.c
636a
}

enum
{
	Hdrspc		= 64,		/* leave room for high-level headers */
	Bdead		= 0x51494F42,	/* "QIOB" */
};

struct
{
	Lock;
	ulong	bytes;
} ialloc;

/*
 *  allocate blocks, round the data base upt to a multiple of BLOCKALIGN.
 */
Block*
allocb(int size)
{
	Block *b;
	ulong addr;
	int n;

	n = sizeof(Block) + size;
	b = poolalloc(mainmem, n+Hdrspc);
	if(b == 0)
		exhausted("Blocks");
	memset(b, 0, sizeof(Block));

	/* align start of data portion by rounding up */
	addr = (ulong)b;
	addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
	b->base = (uchar*)addr;

	/* align end of data portion by rounding down */
	b->lim = ((uchar*)b) + msize(b);
	addr = (ulong)(b->lim);
	addr = addr & ~(BLOCKALIGN-1);
	b->lim = (uchar*)addr;

	/* leave sluff at beginning for added headers */
	b->rp = b->lim - ROUND(size, BLOCKALIGN);
	if(b->rp < b->base)
		panic("allocb");
	b->wp = b->rp;
	tagwithpc(b, getcallerpc(&size));

	return b;
}

/*
 *  interrupt time allocation
 */
Block*
iallocb(int size)
{
	Block *b;
	ulong addr;
	int n;

	if(ialloc.bytes > conf.ialloc){
		print("iallocb: limited %lud/%lud\n",
			ialloc.bytes, conf.ialloc);
		return 0;
	}

	n = sizeof(Block) + size;
	b = poolalloc(mainmem, n+Hdrspc);
	if(b == 0){
		print("iallocb: no memory %lud/%lud\n",
			ialloc.bytes, conf.ialloc);
		return nil;
	}
	memset(b, 0, sizeof(Block));

	/* align start of data portion by rounding up */
	addr = (ulong)b;
	addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
	b->base = (uchar*)addr;

	/* align end of data portion by rounding down */
	b->lim = ((uchar*)b) + msize(b);
	addr = (ulong)(b->lim);
	addr = addr & ~(BLOCKALIGN-1);
	b->lim = (uchar*)addr;

	/* leave sluff at beginning for added headers */
	b->rp = b->lim - ROUND(size, BLOCKALIGN);
	if(b->rp < b->base)
		panic("allocb");
	b->wp = b->rp;

	b->flag = BINTR;

	ilock(&ialloc);
	ialloc.bytes += b->lim - b->base;
	iunlock(&ialloc);
	tagwithpc(b, getcallerpc(&size));

	return b;
}

void
freeb(Block *b)
{
	void *dead = (void*)Bdead;

	if(b == nil)
		return;

	/*
	 * drivers which perform non cache coherent DMA manage their own buffer
	 * pool of uncached buffers and provide their own free routine.
	 */
	if(b->free) {
		b->free(b);
		return;
	}
	if(b->flag & BINTR) {
		ilock(&ialloc);
		ialloc.bytes -= b->lim - b->base;
		iunlock(&ialloc);
	}

	/* poison the block in case someone is still holding onto it */
	b->next = dead;
	b->rp = dead;
	b->wp = dead;
	b->lim = dead;
	b->base = dead;

	poolfree(mainmem, b);
}

void
checkb(Block *b, char *msg)
{
	void *dead = (void*)Bdead;

	if(b == dead)
		panic("checkb b %s %lux", msg, b);
	if(b->base == dead || b->lim == dead || b->next == dead
	  || b->rp == dead || b->wp == dead){
		print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",
			b->base, b->lim, b->next);
		print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);
		panic("checkb dead: %s\n", msg);
	}

	if(b->base > b->lim)
		panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);
	if(b->rp < b->base)
		panic("checkb 1 %s %lux %lux", msg, b->base, b->rp);
	if(b->wp < b->base)
		panic("checkb 2 %s %lux %lux", msg, b->base, b->wp);
	if(b->rp > b->lim)
		panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim);
	if(b->wp > b->lim)
		panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);

}

void
iallocsummary(void)
{
	print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
.
447,451c
	if(nv != nil)
		tagwithpc(nv, getcallerpc(&v));
.
423d
418,421c
	if(v != nil)
.
407,411c
	if(v != nil)
		tagwithpc(v, getcallerpc(&size));
.
391,395c
	tagwithpc(v, getcallerpc(&size));
.
371,375c
	if(v != nil)
		tagwithpc(v, getcallerpc(&size));
.
362a
static void
tagwithpc(void *v, ulong pc)
{
	Bhdr *h;

	D2B(h, v);
	B2T(h)->pad = pc;
}

.
## diffname port/alloc.c 1999/0603
## diff -e /n/emeliedump/1999/0527/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0603/sys/src/brazil/port/alloc.c
363c
void
.
## diffname port/alloc.c 1999/0710
## diff -e /n/emeliedump/1999/0603/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0710/sys/src/brazil/port/alloc.c
542,796d
540d
515,538c
	u = v;
	u[-2] = pc;
.
496,513c
	ulong *u;
	if(v == nil)
.
494c
tagwithpc(void *v, ulong pc)
.
491d
484,489c
	poolsummary(mainmem);
	poolsummary(imagmem);
.
482c
mallocsummary(void)
.
480d
466,477c
	print("%s max %lud cur %lud free %lud alloc %lud\n", p->name,
		p->maxsize, p->cursize, p->curfree, p->curalloc);
.
464c
poolsummary(Pool *p)
.
462d
459c
	return mallocz(n*szelem, 1);
.
450,453c
	return poolmsize(mainmem, (uchar*)v-8)-8;
.
447c
ulong
.
431,444c
	nv = (uchar*)v-8;
	nsize = size+8;
	if(l = poolrealloc(mainmem, nv, nsize))
		return l+2;
	return nil;
.
427a
	if(size == 0) {
		free(v);
		return nil;
	}
.
426c
	long nsize;
.
424c
	ulong *l;
.
417,418c
	if(v != nil) {
		poolfree(mainmem, (uchar*)v-8);
	}
.
409,410d
406c
	if(size == 0)
		return nil;

	v = poolalloc(mainmem, size+8);
	if(v != nil) {
		l = v;
		l[0] = getcallerpc(&size);
		v = l+2;
	}
.
404a
	ulong *l;
.
396,397d
385,394c
	v = poolalloc(mainmem, size+8);
	if(v != nil) {
		l = v;
		l[0] = getcallerpc(&size);
		v = l+2;
		memset(v, 0, size);
.
377,383c
	if(size == 0)
		return nil;
.
374a
	ulong *l;
.
298,371d
215,295c
	l = v;
	l[0] = getcallerpc(&size);
	v = l+2;
	memset(v, 0, size);
	return v;
.
189,213c
	for(;;) {
		v = poolalloc(mainmem, size+8);
		if(v != nil)
			break;
		tsleep(&up->sleep, return0, 0, 100);
.
186,187c
	void *v;
	ulong *l;
.
184c
smalloc(ulong size)
.
50,182d
47,48c
Pool*	mainmem = &pmainmem;
Pool*	imagmem = &pimagmem;
.
34,44c
static Pool pimagmem = {
	.name=	"Image",
	.maxsize=	16*1024*1024,
	.minarena=	2*1024*1024,
	.quantum=	32,
	.alloc=	xalloc,
	.merge=	xmerge,
	.flags=	0,
.
9,31c
static Pool pmainmem = {
	.name=	"Main",
	.maxsize=	4*1024*1024,
	.minarena=	128*1024,
	.quantum=	32,
	.alloc=	xalloc,
	.merge=	xmerge,
	.flags=	0,
.
7a
#include	"pool.h"
.
4d
## diffname port/alloc.c 1999/0711
## diff -e /n/emeliedump/1999/0710/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0711/sys/src/brazil/port/alloc.c
75,77d
57,59d
## diffname port/alloc.c 1999/0712
## diff -e /n/emeliedump/1999/0711/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0712/sys/src/brazil/port/alloc.c
145,146c
	base = b;
	ptr = b;
	limit = B2LIMIT(b);

	while(base != nil) {
		print("\tbase #%.8lux ptr #%.8lux", base, ptr);
		if(ptr->magic == MAGIC_A)
			print("\tA%.5d\n", ptr->size);
		else if(ptr->magic == MAGIC_E)
			print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize);
		else
			print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n",
				ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
		ptr = B2NB(ptr);
		if(ptr >= limit) {
			print("link to #%.8lux\n", base->clink);
			base = base->clink;
			if(base == nil)
				break;
			ptr = base;
			limit = B2LIMIT(base);
		}
	}
	return;
}
*/

void
poolsetparam(char *name, ulong maxsize, int quanta, int chunk, void (*move)(void*, void*))
{
	Pool *p;
	int i;

	for(i=0; i<table.n; i++){
		p = &table.pool[i];
		if(strcmp(name, p->name) == 0){
			if(maxsize != 0)
				p->maxsize = maxsize;
			if(quanta != 0)
				p->quanta = quanta;
			if(chunk != 0)
				p->chunk = chunk;
			if(move != nil)
				p->move = move;
			return;
		}
	}
}

int
poolcompact(Pool *pool)
{
	Bhdr *base, *limit, *ptr, *end, *next;
	int compacted, recov, nb;

	if(pool->move == nil || pool->lastfree == pool->nfree)
		return 0;

	pool->lastfree = pool->nfree;

	base = pool->chain;
	ptr = B2NB(base);	/* First Block in arena has clink */
	limit = B2LIMIT(base);
	compacted = 0;

	pool->root = nil;
	end = ptr;
	recov = 0;
	while(base != nil) {
		next = B2NB(ptr);
		if(ptr->magic == MAGIC_A) {
			if(ptr != end) {
				memmove(end, ptr, ptr->size);
				pool->move(B2D(ptr), B2D(end));
				recov = (uchar*)ptr - (uchar*)end;
				compacted = 1;
			}
			end = B2NB(end);
		}
		if(next >= limit) {
			nb = (uchar*)limit - (uchar*)end;
			//print("recovered %d bytes\n", recov);
			//print("%d bytes at end\n", nb);
			USED(recov);
			if(nb > 0){
				if(nb < pool->quanta+1)
					panic("poolcompact: leftover too small\n");
				end->size = nb;
				pooladd(pool, end);
			}
			base = base->clink;
			if(base == nil)
				break;
			ptr = B2NB(base);
			end = ptr;	/* could do better by copying between chains */
			limit = B2LIMIT(base);
			recov = 0;
		} else
			ptr = next;
	}

	return compacted;
.
142,143c
	Bhdr *b, *base, *limit, *ptr;

	b = p->chain;
	if(b == nil)
.
140c
pooldump(Pool *p)
.
138a
/*
.
135,136c
	int i;

	for(i = 0; i < table.n; i++)
		print("Arena: %s cursize=%lud; arenasize=%lud; maxsize=%lud\n",
			table.pool[i].name,
			table.pool[i].cursize,
			table.pool[i].arenasize,
			table.pool[i].maxsize);
.
132a
poolshow(void)
{
	int i;

	for(i = 0; i < table.n; i++) {
		print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
		pooldump(table.pool[i].root, 0, 'R');
	}
}
*/

void
.
131a

.
128,129c
	Bhdr *t;

	if(b == nil)
		return;

	print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n",
		b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
	d++;
	for(t = b->fwd; t != b; t = t->fwd)
		print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
	pooldump(b->left, d, 'l');
	pooldump(b->right, d, 'r');
.
126c
pooldump(Bhdr *b, int d, int c)
.
124a
/*
.
122c
	return malloc(n*szelem);
.
116c
	Bhdr *b;

	D2B(b, v);
	return b->size - BHDRSIZE;
.
106,110c
	D2B(b, v);

	osize = b->size - BHDRSIZE;
	if(osize >= size)
		return v;

	nv = poolalloc(mainmem, size);
	if(nv != nil) {
		memmove(nv, v, osize);
		free(v);
	}
	if(nv != nil)
		tagwithpc(nv, getcallerpc(&v));
	return nv;
.
99,102d
97c
	int osize;
.
95c
	Bhdr *b;
.
87,89c
	if(v != nil)
		poolfree(mainmem, v);
.
80a
	if(v != nil)
		tagwithpc(v, getcallerpc(&size));
.
73,78c
	v = poolalloc(mainmem, size);
.
71d
63a
	memset(v, 0, size);
	tagwithpc(v, getcallerpc(&size));
.
62a
	if(v != nil)
		tagwithpc(v, getcallerpc(&size));
	return v;
}

void*
smalloc(ulong size)
{
	void *v;

	for(;;) {
		v = poolalloc(mainmem, size);
		if(v != nil)
			break;
		tsleep(&up->sleep, return0, 0, 100);
.
57,61c
	v = poolalloc(mainmem, size);
	if(v != nil)
.
54d
50a
void
poolfree(Pool *p, void *v)
{
	Bhdr *b, *c;

	D2B(b, v);

	ilock(&p->l);
	p->nfree++;
	p->cursize -= b->size;

	c = B2NB(b);
	if(c->magic == MAGIC_F) {	/* Join forward */
		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 */
		pooldel(p, c);
		b->magic = 0;
		c->size += b->size;
		b = c;
		B2T(b)->hdr = b;
	}

	pooladd(p, b);
	iunlock(&p->l);
}

int
poolread(char *va, int count, ulong offset)
{
	Pool *p;
	int n, i, signed_off;

	n = 0;
	signed_off = offset;
	for(i = 0; i < table.n; i++) {
		p = &table.pool[i];
		n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n",
			p->cursize,
			p->maxsize,
			p->hw,
			p->nalloc,
			p->nfree,
			p->nbrk,
			p->name);

		if(signed_off > 0) {
			signed_off -= n;
			if(signed_off < 0) {
				memmove(va, va+n+signed_off, -signed_off);
				n = -signed_off;
			}
			else
				n = 0;
		}

	}
	return n;
}

void
tagwithpc(void *v, ulong pc)
{
	Bhdr *h;

	D2B(h, v);
	B2T(h)->pad = pc;
}

.
44,48c
	if(q != nil) {
		pooldel(p, q);
		q->magic = MAGIC_A;
		frag = q->size - size;
		if(frag < (size>>2)) {
			p->cursize += q->size;
			if(p->cursize > p->hw)
				p->hw = p->cursize;
			iunlock(&p->l);
			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;
		iunlock(&p->l);
		return B2D(q);
	}

	ns = p->chunk;
	if(size > ns)
		ns = size;
	ldr = p->quanta+1;

	alloc = ns+ldr+sizeof(t->magic);
	p->arenasize += alloc;
	if(p->arenasize > p->maxsize) {
		p->arenasize -= alloc;

		if(poolcompact(p)) {
			iunlock(&p->l);
			return poolalloc(p, size);
		}

		iunlock(&p->l);
		print("%s arena too large: size %ld cursize %lud arenasize %lud maxsize %lud\n",
			 p->name, size, p->cursize, p->arenasize, p->maxsize);
		return nil;
	}

	p->nbrk++;
	t = xalloc(alloc);
	if(t == nil) {
		iunlock(&p->l);
		return nil;
	}

	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;
	iunlock(&p->l);
	return B2D(t);
.
38,42c
	if(size < 0 || size >= 1024*1024*1024)	/* for sanity and to avoid overflow */
		return nil;
	size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);

	ilock(&p->l);
	p->nalloc++;

	t = p->root;
	q = nil;
	while(t) {
		if(t->size == size) {
			pooldel(p, t);
			t->magic = MAGIC_A;
			p->cursize += t->size;
			if(p->cursize > p->hw)
				p->hw = p->cursize;
			iunlock(&p->l);
			return B2D(t);
		}
		if(size < t->size) {
			q = t;
			t = t->left;
		}
		else
			t = t->right;
.
35,36c
	Bhdr *q, *t;
	int alloc, ldr, ns, frag;
.
33c
poolalloc(Pool *p, long size)
.
31a
int	poolcompact(Pool*);

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->fwd = t->fwd;
			q->fwd->prev = q;
			q->prev = t;
			t->fwd = 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;
}

.
29,30c
Pool*	mainmem = &table.pool[0];
Pool*	imagmem = &table.pool[1];
.
19,26c
struct
{
	int	n;
	Pool	pool[MAXPOOL];
	Lock	l;
} table = {
	2,
	{
		{ "Main",	 4*1024*1024, 31,  128*1024 },
		{ "Image",	 16*1024*1024, 31, 2*1024*1024 },
	}
.
9,16c
#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

struct Pool
{
	char*	name;
	ulong	maxsize;
	int	quanta;
	int	chunk;
	ulong	cursize;
	ulong	arenasize;
	ulong	hw;
	Lock	l;
	Bhdr*	root;
	Bhdr*	chain;
	int	nalloc;
	int	nfree;
	int	nbrk;
	int	lastfree;
	void	(*move)(void*, void*);
.
7d
3a
#include	"pool.h"
.
## diffname port/alloc.c 1999/0713
## diff -e /n/emeliedump/1999/0712/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0713/sys/src/brazil/port/alloc.c
515,616c
	u = v;
	u[-2] = pc;
.
510,513c
	ulong *u;
	if(v == nil)
.
508c
tagwithpc(void *v, ulong pc)
.
506d
496,503c
	poolsummary(mainmem);
	poolsummary(imagmem);
.
482,493d
480d
466,477c
	print("%s max %lud cur %lud free %lud alloc %lud\n", p->name,
		p->maxsize, p->cursize, p->curfree, p->curalloc);
.
464c
poolsummary(Pool *p)
.
462d
459c
	return mallocz(n*szelem, 1);
.
450,453c
	return poolmsize(mainmem, (uchar*)v-8)-8;
.
431,444c
	nv = (uchar*)v-8;
	nsize = size+8;
	if(l = poolrealloc(mainmem, nv, nsize))
		return l+2;
	return nil;
.
427a
	if(size == 0) {
		free(v);
		return nil;
	}
.
426c
	long nsize;
.
424c
	ulong *l;
.
417,418c
	if(v != nil) {
if(0)		if(mainmem->flags & POOL_STUPID) {
			print("A");
			delay(50);
		}
		poolfree(mainmem, (uchar*)v-8);
if(0)		if(mainmem->flags & POOL_STUPID) {
			print("a");
			delay(50);
		}
	}
.
409,410d
406c
	v = poolalloc(mainmem, size+8);
	if(v != nil) {
		l = v;
		l[0] = getcallerpc(&size);
		v = l+2;
	}
.
404a
	ulong *l;
.
396,397d
380,394d
377,378c
	v = poolalloc(mainmem, size+8);
	if(v != nil) {
		l = v;
		l[0] = getcallerpc(&size);
		v = l+2;
.
374a
	ulong *l;
.
298,371d
215,295c
	l = v;
	l[0] = getcallerpc(&size);
	v = l+2;
	memset(v, 0, size);
	return v;
.
189,213c
	for(;;) {
		v = poolalloc(mainmem, size+8);
		if(v != nil)
			break;
		tsleep(&up->sleep, return0, 0, 100);
.
186,187c
	void *v;
	ulong *l;
.
184c
smalloc(ulong size)
.
50,182d
47,48c
Pool*	mainmem = &pmainmem;
Pool*	imagmem = &pimagmem;
.
34,44c
static Pool pimagmem = {
	.name=	"Image",
	.maxsize=	16*1024*1024,
	.minarena=	2*1024*1024,
	.quantum=	32,
	.alloc=	xalloc,
	.merge=	xmerge,
	.flags=	0,
.
15,31c
static Pool pmainmem = {
	.name=	"Main",
	.maxsize=	4*1024*1024,
	.minarena=	128*1024,
	.quantum=	32,
	.alloc=	xalloc,
	.merge=	xmerge,
	.flags=	0,
.
9,13c
enum {
	POOL_STUPID = 0x80000000,
};
.
7a
#include	"pool.h"
.
4d
## diffname port/alloc.c 1999/0714
## diff -e /n/emeliedump/1999/0713/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0714/sys/src/brazil/port/alloc.c
160a
ulong
getmalloctag(void *v)
{
	USED(v);
	if(Npadlong <= MallocOffset)
		return ~0;
	return ((ulong*)v)[-Npadlong+MallocOffset];
}

ulong
getrealloctag(void *v)
{
	USED(v);
	if(Npadlong <= ReallocOffset)
		return ((ulong*)v)[-Npadlong+ReallocOffset];
	return ~0;
}
.
158c
	u[-Npadlong+ReallocOffset] = pc;
.
155c
	USED(v, pc);
	if(Npadlong <= ReallocOffset || v == nil)
.
147,153d
145c
setrealloctag(void *v, ulong pc)
.
140,141c
	ulong *u;
	USED(v, pc);
	if(Npadlong <= MallocOffset || v == nil)
		return;
	u = v;
	u[-Npadlong+MallocOffset] = pc;
.
138c
setmalloctag(void *v, ulong pc)
.
134c
	void *v;
	if(v = mallocz(n*szelem, 1))
		setmalloctag(v, getcallerpc(&n));
	return v;
.
128c
	return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);
.
118,122c
	if(nv = poolrealloc(mainmem, v, size)){
		nv = (ulong*)nv+Npadlong;
		setrealloctag(nv, getcallerpc(&v));
		if(v == nil)
			setmalloctag(nv, getcallerpc(&v));
	}		
	return nv;
.
111,116c
	if(v != nil)
		v = (ulong*)v-Npadlong;
	if(Npadlong !=0 && size != 0)
		size += Npadlong*sizeof(ulong);
.
109d
107d
91,101c
	if(v != nil)
		poolfree(mainmem, (ulong*)v-Npadlong);
.
77,81c
	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
	if(Npadlong && v != nil){
		v = (ulong*)v+Npadlong;
		setmalloctag(v, getcallerpc(&size));
		setrealloctag(v, 0);
.
75d
61,65c
	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
	if(Npadlong && v != nil) {
		v = (ulong*)v+Npadlong;
		setmalloctag(v, getcallerpc(&size));
		setrealloctag(v, 0);
.
58d
48,50c
	if(Npadlong){
		v = (ulong*)v+Npadlong;
		setmalloctag(v, getcallerpc(&size));
	}
.
43c
		v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
.
40d
35a
/*
 * because we can't print while we're holding the locks, 
 * we have the save the message and print it once we let go.
 */
static void
poolprint(Pool *p, char *fmt, ...)
{
	va_list v;
	int n;

	va_start(v, fmt);
	n = doprint(p->msg, p->msg+sizeof p->msg, fmt, v)-p->msg;
	va_end(v);
	if(n >= sizeof p->msg);
		n = sizeof(p->msg)-1;
	if(n < 0)
		n = 0;
	p->msg[n] = 0;
}

static void
ppanic(Pool *p, char *fmt, ...)
{
	va_list v;
	int n;

	va_start(v, fmt);
	n = doprint(p->msg, p->msg+sizeof p->msg, fmt, v)-p->msg;
	va_end(v);
	if(n >= sizeof p->msg);
		n = sizeof(p->msg)-1;
	if(n < 0)
		n = 0;
	p->msg[n] = 0;
	iunlock(&p->lk);
	panic("%s", p->msg);
}

static void
plock(Pool *p)
{
	ilock(&p->lk);
	p->msg[0] = 0;
}

static void
punlock(Pool *p)
{
	char msg[sizeof p->msg];

	if(p->msg[0] == 0){
		iunlock(&p->lk);
		return;
	}

	memmove(msg, p->msg, sizeof msg);
	iunlock(&p->lk);
	print("%.*s", sizeof p->msg, msg);
}

void
poolsummary(Pool *p)
{
	print("%s max %lud cur %lud free %lud alloc %lud\n", p->name,
		p->maxsize, p->cursize, p->curfree, p->curalloc);
}

void
mallocsummary(void)
{
	poolsummary(mainmem);
	poolsummary(imagmem);
}

/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
/* - except the code for malloc(), which alternately doesn't clear or does. */
/* - except the code for smalloc(), which lives only in the kernel. */

/*
 * Npadlong is the number of 32-bit longs to leave at the beginning of 
 * each allocated buffer for our own bookkeeping.  We return to the callers
 * a pointer that points immediately after our bookkeeping area.  Incoming pointers
 * must be decremented by that much, and outgoing pointers incremented.
 * The malloc tag is stored at MallocOffset from the beginning of the block,
 * and the realloc tag at ReallocOffset.  The offsets are from the true beginning
 * of the block, not the beginning the caller sees.
 *
 * The extra if(Npadlong != 0) in various places is a hint for the compiler to
 * compile out function calls that would otherwise be no-ops.
 */

/*	non tracing
 *
enum {
	Npadlong	= 0,
	MallocOffset = 0,
	ReallocOffset = 0,
};
 *
 */

/* tracing */
enum {
	Npadlong	= 2,
	MallocOffset = 0,
	ReallocOffset = 1
};


.
30a

	.lock=	plock,
	.unlock=	punlock,
	.print=	poolprint,
	.panic=	ppanic,
.
20c
	.flags=	POOL_TOLERANCE,

	.lock=	plock,
	.unlock=	punlock,
	.print=	poolprint,
	.panic=	ppanic,
.
9,11c
static void poolprint(Pool*, char*, ...);
static void ppanic(Pool*, char*, ...);
static void plock(Pool*);
static void punlock(Pool*);
.
## diffname port/alloc.c 1999/0825
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0825/sys/src/brazil/port/alloc.c
102,104c
	memmove(msg, pv->msg, sizeof msg);
	iunlock(&pv->lk);
	print("%.*s", sizeof pv->msg, msg);
.
97,98c
	pv = p->private;
	if(pv->msg[0] == 0){
		iunlock(&pv->lk);
.
95c
	Private *pv;
	char msg[sizeof pv->msg];
.
88,89c
	Private *pv;

	pv = p->private;
	ilock(&pv->lk);
	pv->msg[0] = 0;
.
80,82c
	pv->msg[n] = 0;
	iunlock(&pv->lk);
	panic("%s", pv->msg);
.
76,77c
	if(n >= sizeof pv->msg);
		n = sizeof(pv->msg)-1;
.
74c
	n = doprint(pv->msg, pv->msg+sizeof pv->msg, fmt, v)-pv->msg;
.
72a
	pv = p->private;
.
71a
	Private *pv;
.
64c
	pv->msg[n] = 0;
.
60,61c
	if(n >= sizeof pv->msg);
		n = sizeof(pv->msg)-1;
.
58c
	n = doprint(pv->msg, pv->msg+sizeof pv->msg, fmt, v)-pv->msg;
.
56a
	pv = p->private;
.
55a
	Private *pv;
.
41a

	.private=	&pimagpriv,
.
28a
static Private pimagpriv;
.
26a

	.private=	&pmainpriv,
.
13a
typedef struct Private	Private;
struct Private {
	Lock		lk;
	char		msg[128];	/* a rock for messages to be printed at unlock */
};

static Private pmainpriv;
.
7c
#include	<pool.h>
.
## diffname port/alloc.c 2000/0120
## diff -e /n/emeliedump/1999/0825/sys/src/brazil/port/alloc.c /n/emeliedump/2000/0120/sys/src/9/port/alloc.c
98c
	panic("%s", msg);
.
92,96c
	memmove(msg, pv->msg, sizeof msg);
.
90c
	doprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
.
86a
	char msg[sizeof pv->msg];
.
74,78d
72c
	doprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
.
17c
	char		msg[256];	/* a rock for messages to be printed at unlock */
.
## diffname port/alloc.c 2000/0229
## diff -e /n/emeliedump/2000/0120/sys/src/9/port/alloc.c /n/emeliedump/2000/0229/sys/src/9/port/alloc.c
67d
## diffname port/alloc.c 2000/0407
## diff -e /n/emeliedump/2000/0229/sys/src/9/port/alloc.c /n/emeliedump/2000/0407/sys/src/9/port/alloc.c
79d
## diffname port/alloc.c 2002/0217
## diff -e /n/emeliedump/2000/0407/sys/src/9/port/alloc.c /n/emeliedump/2002/0217/sys/src/9/port/alloc.c
84c
	vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
.
71c
	vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v);
.
## diffname port/alloc.c 2002/0425
## diff -e /n/emeliedump/2002/0217/sys/src/9/port/alloc.c /n/emeliedump/2002/0425/sys/src/9/port/alloc.c
197a
	memset(v, 0, size);
.
196d
192c
	if(v == nil)
		return nil;
	if(Npadlong){
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].