~kris/9p

9hist

70fd5bf906c6315f2a11a7302a479823dba0350f — David du Colombier 36 years ago ecf04c5
Plan 9 from Bell Labs 1990-03-27
4 files changed, 231 insertions(+), 50 deletions(-)

M gnot/dat.h
M gnot/errno.h
M gnot/main.c
M port/devbit.c
M gnot/dat.h => gnot/dat.h +2 -0
@@ 130,6 130,8 @@ struct Conf
	int	nqueue;		/* stream queues */
	int	nblock;		/* stream blocks */
	int	nsrv;		/* public servers (devsrv.c) */
	int	nbitmap;	/* bitmap structs (devbit.c) */
	int	nbitbyte;	/* bytes of bitmap data (devbit.c) */
};

struct Dev

M gnot/errno.h => gnot/errno.h +3 -1
@@ 46,6 46,8 @@ enum{
	Edestotl,	/* datakit destination out to lunch */
	Enetotl,	/* datakit controller out to lunch */
	Erejected,	/* datakit destination rejected call */
	Ebadblt,	/* bad bitblt or bitctl request */
	Ebadblt,	/* bad bitblt or bitmap request */
	Enobitmap,	/* out of bitmap descriptors */
	Enobitstore,	/* out of bitmap storage */
	Egreg,		/* it's all greg's fault */
};

M gnot/main.c => gnot/main.c +2 -0
@@ 253,4 253,6 @@ confinit(void)
	conf.nqueue = 5 * conf.nstream;
	conf.nblock = 12 * conf.nstream;
	conf.nsrv = 32;
	conf.nbitmap = 100;
	conf.nbitbyte = 200*1024;
}

M port/devbit.c => port/devbit.c +224 -49
@@ 9,14 9,31 @@

#include	"gnot.h"

extern	Bitmap	screen;
/*
 * Some fields in Bitmaps are overloaded:
 *	ldepth = -1 means free.
 *	base is next pointer when free.
 * Arena is a word containing N, followed by a pointer to its bitmap,
 * followed by N blocks.  The bitmap pointer is zero if block is free. 
 */

struct{
	Ref;
	int	bltuse;
	QLock	blt;		/* a group of bitblts in a single write is atomic */
	Bitmap	*map;		/* arena */
	Bitmap	*free;		/* free list */
	ulong	*words;		/* storage */
	ulong	nwords;		/* total in arena */
	ulong	*wfree;		/* pointer to next free word */
	int	lastid;		/* last allocated bitmap id */
}bit;

#define	FREE	0x80000000
void	bitcompact(void);
void	bitfree(Bitmap*);
extern	Bitmap	screen;

enum{
	Qdir,
	Qbitblt,


@@ 31,6 48,22 @@ Dirtab bitdir[]={
void
bitreset(void)
{
	int i;
	Bitmap *bp;

	bit.map = ialloc(conf.nbitmap * sizeof(Bitmap), 0);
	for(i=0,bp=bit.map; i<conf.nbitmap; i++,bp++){
		bp->ldepth = -1;
		bp->base = (ulong*)(bp+1);
	}
	bp--;
	bp->base = 0;
	bit.map[0] = screen;	/* bitmap 0 is screen */
	bit.free = bit.map+1;
	bit.lastid = -1;
	bit.words = ialloc(conf.nbitbyte, 0);
	bit.nwords = conf.nbitbyte/sizeof(ulong);
	bit.wfree = bit.words;
}

void


@@ 74,15 107,12 @@ bitopen(Chan *c, int omode)
		if(omode != OREAD)
			error(0, Eperm);
	}else{
		/*
		 * Always open #b/bitblt first
		 */
		lock(&bit);
		if((c->qid==Qbitblt && bit.bltuse)
		|| (c->qid!=Qbitblt && !bit.bltuse)){
		if(bit.bltuse){
			unlock(&bit);
			error(0, Einuse);
		}
		bit.lastid = -1;
		unlock(&bit);
		incref(&bit);
	}


@@ 113,25 143,60 @@ bitwstat(Chan *c, char *db)
void
bitclose(Chan *c)
{
	int i;
	Bitmap *bp;

	if(c->qid != CHDIR){
		lock(&bit);
		if(--bit.ref == 0)
		lock(&bit);			/* FREE ALL THE BITMAPS: BUG */
		if(--bit.ref == 0){
			for(i=1,bp=&bit.map[1]; i<conf.nbitmap; i++,bp++)
				if(bp->ldepth >= 0)
					bitfree(bp);
			bit.bltuse = 0;
		}
		unlock(&bit);
	}
}

#define	GSHORT(p)		(((p)[0]<<0) | ((p)[1]<<8))
#define	GLONG(p)		((GSHORT(p)<<0) | (GSHORT(p+2)<<16))

long
bitread(Chan *c, void *va, long n)
{
	uchar *p;

	if(c->qid & CHDIR)
		return devdirread(c, va, n, bitdir, NBIT, devgen);

	error(0, Egreg);
	if(c->qid != Qbitblt)
		error(0, Egreg);
	p = va;
	qlock(&bit.blt);
	if(waserror()){
		qunlock(&bit.blt);
		nexterror();
	}
	/*
	 * Fuss about and figure out what to say.
	 */
	if(bit.lastid > 0){
		if(n < 3)
			error(0, Ebadblt);
		p[0] = 'A';
		p[1] = bit.lastid;
		p[2] = bit.lastid>>8;
		bit.lastid = -1;
		n = 3;
		goto done;
	}
	error(0, Ebadblt);

    done:
	qunlock(&bit.blt);
	return n;
}

#define	SHORT(p)	(((p)[0]<<0) | ((p)[1]<<8))
#define	LONG(p)		((SHORT(p)<<0) | (SHORT(p+2)<<16))

long
bitwrite(Chan *c, void *va, long n)


@@ 139,55 204,133 @@ bitwrite(Chan *c, void *va, long n)
	uchar *p;
	long m;
	long v;
	ulong l, nw, ws;
	Point pt;
	Rectangle rect;
	Bitmap *src, *dst;
	Bitmap *bp, *src, *dst;

	if(c->qid == CHDIR)
		error(0, Eisdir);

	if(c->qid != Qbitblt)
		error(0, Egreg);

	p = va;
	m = n;
	switch(c->qid){
	case Qbitblt:
		qlock(&bit.blt);
		if(waserror()){
			qunlock(&bit.blt);
			nexterror();
		}
		while(m > 0)
			switch(*p){
			case 'b':
				if(m < 31)
					error(0, Ebadblt);
				v = SHORT(p+1);
				if(v != 0)		/* BUG */
					error(0, Ebadblt);
				dst = &screen;
				pt.x = LONG(p+3);
				pt.y = LONG(p+7);
				v = SHORT(p+11);
				if(v != 0)		/* BUG */
					error(0, Ebadblt);
				src = &screen;
				rect.min.x = LONG(p+13);
				rect.min.y = LONG(p+17);
				rect.max.x = LONG(p+21);
				rect.max.y = LONG(p+25);
				v = SHORT(p+29);
				bitblt(dst, pt, src, rect, v);
				m -= 31;
				p += 31;
				break;
			default:
	qlock(&bit.blt);
	if(waserror()){
		qunlock(&bit.blt);
		nexterror();
	}
	while(m > 0)
		switch(*p){
		case 'a':
			/*
			 * allocate:
			 *	'a'		1
			 *	ldepth		1
			 *	Rectangle	16
			 * next read returns allocated bitmap id
			 */
			if(m < 18)
				error(0, Ebadblt);
			v = *(p+1);
			if(v != 0)	/* BUG */
				error(0, Ebadblt);
			ws = 1<<(5-v);	/* pixels per word */
			if(bit.free == 0)
				error(0, Enobitmap);
			rect.min.x = GLONG(p+2);
			rect.min.y = GLONG(p+6);
			rect.max.x = GLONG(p+10);
			rect.max.y = GLONG(p+14);
			if(rect.min.x >= 0)
				l = (rect.max.x+ws-1)/ws - rect.min.x/ws;
			else{	/* make positive before divide */
				long t;
				t = (-rect.min.x)+ws-1;
				t = (t/ws)*ws;
				l = (t+rect.max.x+ws-1)/ws;
			}
		qunlock(&bit.blt);
		break;
			nw = l*Dy(rect);
			if(bit.wfree+l+2 > bit.words+bit.nwords){
				bitcompact();
				if(bit.wfree+l+1 > bit.words+bit.nwords)
					error(0, Enobitstore);
			}
			bp = bit.free;
			bit.free = (Bitmap*)(bp->base);
			*bit.wfree++ = nw;
			*bit.wfree++ = (ulong)bp;
			bp->base = bit.wfree;
			memset(bp->base, 0, nw*sizeof(ulong));
			bit.wfree += nw;
			bp->zero = l*rect.min.y;
			if(rect.min.x >= 0)
				bp->zero += rect.min.x/ws;
			else
				bp->zero -= (-rect.min.x+ws-1)/ws;
			bp->zero = -bp->zero;
			bp->width = l;
			bp->ldepth = v;
			bp->rect = rect;
			bp->cache = 0;
			bit.lastid = bp-bit.map;
			m -= 18;
			p += 18;
			break;

	default:
		error(0, Egreg);
	}
		case 'b':
			/*
			 * bitblt
			 *	'b'		1
			 *	dst id		2
			 *	dst Point	8
			 *	src id		2
			 *	src Rectangle	16
			 *	code		2
			 */
			if(m < 31)
				error(0, Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || dst->ldepth < 0)
				error(0, Ebadblt);
			pt.x = GLONG(p+3);
			pt.y = GLONG(p+7);
			v = GSHORT(p+11);
			src = &bit.map[v];
			if(v<0 || v>=conf.nbitmap || src->ldepth < 0)
				error(0, Ebadblt);
			rect.min.x = GLONG(p+13);
			rect.min.y = GLONG(p+17);
			rect.max.x = GLONG(p+21);
			rect.max.y = GLONG(p+25);
			v = GSHORT(p+29);
			bitblt(dst, pt, src, rect, v);
			m -= 31;
			p += 31;
			break;

		case 'f':
			/*
			 * free
			 *	'f'		1
			 *	id		2
			 */
			if(m < 3)
				error(0, Ebadblt);
			v = GSHORT(p+1);
			dst = &bit.map[v];
			if(v >= conf.nbitmap || dst->ldepth<0)
				error(0, Ebadblt);
			bitfree(dst);
			m -= 3;
			p += 3;
			break;
		}

	qunlock(&bit.blt);
	return n;
}



@@ 202,3 345,35 @@ biterrstr(Error *e, char *buf)
{
	rooterrstr(e, buf);
}

void
bitfree(Bitmap *bp)
{
	bp->base[1] = 0;
	bp->ldepth = -1;
	bp->base = (ulong*)bit.free;
	bit.free = bp;
}

void
bitcompact(void)
{
	ulong *p1, *p2;

print("bitcompact\n");
	p1 = p2 = bit.words;
	while(p2 < bit.wfree){
		if(p2[1] == 0){
			p2 += 2 + p2[0];
			continue;
		}
		if(p1 != p2){
			memcpy(p1, p2, (2+p2[0])*sizeof(ulong));
			((Bitmap*)p1[1])->base = p1+2;
		}
		p2 += 2 + p1[0];
		p1 += 2 + p1[0];
	}
	bit.wfree = p1;
print("bitcompact done\n");
}