From 70fd5bf906c6315f2a11a7302a479823dba0350f Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 27 Mar 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-03-27 --- gnot/dat.h | 2 + gnot/errno.h | 4 +- gnot/main.c | 2 + port/devbit.c | 273 +++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 231 insertions(+), 50 deletions(-) diff --git a/gnot/dat.h b/gnot/dat.h index 0e448613d366161de393a479513917a8d0e4acf6..13c6b7fe9edaf1e6fdf626329fe84a0290a0a4c5 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -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 diff --git a/gnot/errno.h b/gnot/errno.h index fcfd507377d58b40bfea70a4f1333a94cc428ae4..98b6518f4e3ab0458ab091a95d7e66dba45a3ef4 100644 --- a/gnot/errno.h +++ b/gnot/errno.h @@ -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 */ }; diff --git a/gnot/main.c b/gnot/main.c index 0365e9d7f4be457716c3ee13955d53d5c0a04087..b562ba44bfd70667ba28e227438fc39466b7494c 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -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; } diff --git a/port/devbit.c b/port/devbit.c index e7c7fbc9e1439fc697c4c32ab1d49c532fdde0d7..c842e548030f0bea074a25cfce93a4436c67f3e3 100644 --- a/port/devbit.c +++ b/port/devbit.c @@ -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; ildepth = -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]; ildepth >= 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"); +}