D bitsy/devsac.c => bitsy/devsac.c +0 -592
@@ 1,592 0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-/*
- * definitions from the old 9P. we need these because sac files
- * are encoded using the old definitions.
- */
-#define NAMELEN 28
-
-#define CHDIR 0x80000000 /* mode bit for directories */
-#define CHAPPEND 0x40000000 /* mode bit for append only files */
-#define CHEXCL 0x20000000 /* mode bit for exclusive use files */
-#define CHMOUNT 0x10000000 /* mode bit for mounted channel */
-#define CHREAD 0x4 /* mode bit for read permission */
-#define CHWRITE 0x2 /* mode bit for write permission */
-#define CHEXEC 0x1 /* mode bit for execute permission */
-
-enum
-{
- OPERM = 0x3, /* mask of all permission types in open mode */
- Nram = 512,
- CacheSize = 20,
- OffsetSize = 4, /* size in bytes of an offset */
-};
-
-typedef struct SacPath SacPath;
-typedef struct Sac Sac;
-typedef struct SacHeader SacHeader;
-typedef struct SacDir SacDir;
-typedef struct Cache Cache;
-
-enum {
- Magic = 0x5acf5,
-};
-
-struct SacDir
-{
- char name[NAMELEN];
- char uid[NAMELEN];
- char gid[NAMELEN];
- uchar qid[4];
- uchar mode[4];
- uchar atime[4];
- uchar mtime[4];
- uchar length[8];
- uchar blocks[8];
-};
-
-struct SacHeader
-{
- uchar magic[4];
- uchar length[8];
- uchar blocksize[4];
- uchar md5[16];
-};
-
-
-struct Sac
-{
- SacDir;
- SacPath *path;
-};
-
-struct SacPath
-{
- Ref;
- SacPath *up;
- long blocks;
- int entry;
- int nentry;
-};
-
-struct Cache
-{
- long block;
- ulong age;
- uchar *data;
-};
-
-enum
-{
- Pexec = 1,
- Pwrite = 2,
- Pread = 4,
- Pother = 1,
- Pgroup = 8,
- Powner = 64,
-};
-
-static char *sacfs = "fs.sac";
-static uchar *data;
-static int blocksize;
-static Sac root;
-static Cache cache[CacheSize];
-static ulong cacheage;
-
-static int sacdir(Chan *, SacDir*, uchar*, int);
-static ulong getl(void *p);
-static Sac *saccpy(Sac *s);
-static Sac *saclookup(Sac *s, char *name);
-static int sacdirread(Chan *, uchar *p, long off, long cnt);
-static void loadblock(void *buf, uchar *offset, int blocksize);
-static void sacfree(Sac*);
-
-static void
-pathtoqid(ulong path, Qid *q)
-{
- if(path & CHDIR)
- q->type = QTDIR;
- else
- q->type = QTFILE;
- q->path = path & ~(CHDIR|CHAPPEND|CHEXCL|CHMOUNT);
- q->vers = 0;
-}
-
-static void
-omodetomode(ulong om, ulong *m)
-{
- ulong nm;
-
- nm = om & ~(CHDIR|CHAPPEND|CHEXCL|CHMOUNT);
- if(om & CHDIR)
- nm |= DMDIR;
- *m = nm;
-}
-
-static void
-sacinit(void)
-{
- SacHeader *hdr;
- uchar *p;
- int i;
-
- p = (uchar*)Flash_tar;
- data = tarlookup(p, sacfs, &i);
- if(data == 0) {
- p = (uchar*)Flash_tar+4;
- data = tarlookup(p, sacfs, &i);
- if(data == 0) {
- print("devsac: could not find file: %s\n", sacfs);
- return;
- }
- }
- hdr = (SacHeader*)data;
- if(getl(hdr->magic) != Magic) {
- print("devsac: bad magic\n");
- return;
- }
- blocksize = getl(hdr->blocksize);
- root.SacDir = *(SacDir*)(data + sizeof(SacHeader));
- p = malloc(CacheSize*blocksize);
- if(p == nil)
- error("allocating cache");
- for(i=0; i<CacheSize; i++) {
- cache[i].data = p;
- p += blocksize;
- }
-}
-
-static Chan*
-sacattach(char* spec)
-{
- Chan *c;
- int dev;
-
- dev = atoi(spec);
- if(dev != 0)
- error("bad specification");
-
- // check if init found sac file system in memory
- if(blocksize == 0)
- error("devsac: bad magic");
-
- c = devattach('C', spec);
- pathtoqid(getl(root.qid), &c->qid);
- c->dev = dev;
- c->aux = saccpy(&root);
- return c;
-}
-
-static void listprint(char **name, int nname, int j)
-{
- int i;
-
- print("%d ", j);
- for(i = 0; i< nname; i++)
- print("%s/", name[i]);
- print("\n");
-}
-
-static Walkqid*
-sacwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- Sac *sac;
- int j, alloc;
- Walkqid *wq;
- char *n;
-
- if(nname > 0)
- isdir(c);
-
- alloc = 0;
- wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
- if(waserror()){
- if(alloc && wq->clone!=nil)
- cclose(wq->clone);
- free(wq);
- return nil;
- }
- if(nc == nil){
- nc = devclone(c);
- nc->aux = saccpy(c->aux);
- alloc = 1;
- }
- wq->clone = nc;
-
- for(j=0; j<nname; j++){
- isdir(nc);
- n = name[j];
- if(strcmp(n, ".") == 0){
- wq->qid[wq->nqid++] = nc->qid;
- continue;
- }
- sac = nc->aux;
- sac = saclookup(sac, n);
- if(sac == nil) {
- if(j == 0)
- error(Enonexist);
- kstrcpy(up->errstr, Enonexist, ERRMAX);
- break;
- }
- pathtoqid(getl(sac->qid), &nc->qid);
- wq->qid[wq->nqid++] = nc->qid;
- }
- poperror();
- if(wq->nqid < nname){
-// listprint(name, wq->nqid, j);
- if(alloc)
- cclose(wq->clone);
- wq->clone = nil;
- }
- return wq;
-}
-
-static Chan*
-sacopen(Chan *c, int omode)
-{
- ulong t, mode;
- Sac *sac;
- static int access[] = { 0400, 0200, 0600, 0100 };
-
- sac = c->aux;
- mode = getl(sac->mode);
- if(strcmp(up->user, sac->uid) == 0)
- mode = mode;
- else if(strcmp(up->user, sac->gid) == 0)
- mode = mode<<3;
- else
- mode = mode<<6;
-
- t = access[omode&3];
- if((t & mode) != t)
- error(Eperm);
- c->offset = 0;
- c->mode = openmode(omode);
- c->flag |= COPEN;
- return c;
-}
-
-
-static long
-sacread(Chan *c, void *a, long n, vlong voff)
-{
- Sac *sac;
- char *buf, *buf2;
- int nn, cnt, i, j;
- uchar *blocks;
- long length;
- long off = voff;
-
- buf = a;
- cnt = n;
- if(c->qid.type & QTDIR)
- return sacdirread(c, a, off, cnt);
- sac = c->aux;
- length = getl(sac->length);
- if(off >= length)
- return 0;
- if(cnt > length-off)
- cnt = length-off;
- if(cnt == 0)
- return 0;
- n = cnt;
- blocks = data + getl(sac->blocks);
- buf2 = malloc(blocksize);
- while(cnt > 0) {
- i = off/blocksize;
- nn = blocksize;
- if(nn > length-i*blocksize)
- nn = length-i*blocksize;
- loadblock(buf2, blocks+i*OffsetSize, nn);
- j = off-i*blocksize;
- nn -= j;
- if(nn > cnt)
- nn = cnt;
- memmove(buf, buf2+j, nn);
- cnt -= nn;
- off += nn;
- buf += nn;
- }
- free(buf2);
- return n;
-}
-
-static long
-sacwrite(Chan *, void *, long, vlong)
-{
- error(Eperm);
- return 0;
-}
-
-static void
-sacclose(Chan* c)
-{
- Sac *sac = c->aux;
-
- c->aux = nil;
- sacfree(sac);
-}
-
-static int
-sacstat(Chan *c, uchar *db, int n)
-{
- n = sacdir(c, c->aux, db, n);
- if(n == 0)
- error(Ebadarg);
- return n;
-}
-
-static Sac*
-saccpy(Sac *s)
-{
- Sac *ss;
-
- ss = malloc(sizeof(Sac));
- *ss = *s;
- if(ss->path)
- incref(ss->path);
- return ss;
-}
-
-static SacPath *
-sacpathalloc(SacPath *p, long blocks, int entry, int nentry)
-{
- SacPath *pp = malloc(sizeof(SacPath));
- pp->ref = 1;
- pp->blocks = blocks;
- pp->entry = entry;
- pp->nentry = nentry;
- pp->up = p;
- return pp;
-}
-
-static void
-sacpathfree(SacPath *p)
-{
- if(p == nil)
- return;
- if(decref(p) > 0)
- return;
- sacpathfree(p->up);
- free(p);
-}
-
-
-static void
-sacfree(Sac *s)
-{
- sacpathfree(s->path);
- free(s);
-}
-
-static int
-sacdir(Chan *c, SacDir *s, uchar *db, int n)
-{
- Dir dir;
-
- dir.name = s->name;
- dir.uid = s->uid;
- dir.gid = s->gid;
- dir.muid = s->uid;
- pathtoqid(getl(s->qid), &dir.qid);
- omodetomode(getl(s->mode), &dir.mode);
- dir.length = getl(s->length);
- dir.atime = getl(s->atime);
- dir.mtime = getl(s->mtime);
- dir.type = devtab[c->type]->dc;
- dir.dev = c->dev;
- return convD2M(&dir, db, n);
-}
-
-static void
-loadblock(void *buf, uchar *offset, int blocksize)
-{
- long block, n;
- ulong age;
- int i, j;
-
- block = getl(offset);
- if(block < 0) {
- block = -block;
- cacheage++;
- // age has wraped
- if(cacheage == 0) {
- for(i=0; i<CacheSize; i++)
- cache[i].age = 0;
- }
- j = 0;
- age = cache[0].age;
- for(i=0; i<CacheSize; i++) {
- if(cache[i].age < age) {
- age = cache[i].age;
- j = i;
- }
- if(cache[i].block != block)
- continue;
- memmove(buf, cache[i].data, blocksize);
- cache[i].age = cacheage;
- return;
- }
-
- n = getl(offset+OffsetSize);
- if(n < 0)
- n = -n;
- n -= block;
- if(unsac(buf, data+block, blocksize, n)<0)
- panic("unsac failed!");
- memmove(cache[j].data, buf, blocksize);
- cache[j].age = cacheage;
- cache[j].block = block;
- } else {
- memmove(buf, data+block, blocksize);
- }
-}
-
-static Sac*
-sacparent(Sac *s)
-{
- uchar *blocks;
- SacDir *buf;
- int per, i, n;
- SacPath *p;
-
- p = s->path;
- if(p == nil || p->up == nil) {
- sacpathfree(p);
- *s = root;
- return s;
- }
- p = p->up;
-
- blocks = data + p->blocks;
- per = blocksize/sizeof(SacDir);
- i = p->entry/per;
- n = per;
- if(n > p->nentry-i*per)
- n = p->nentry-i*per;
- buf = malloc(per*sizeof(SacDir));
- loadblock(buf, blocks + i*OffsetSize, n*sizeof(SacDir));
- s->SacDir = buf[p->entry-i*per];
- free(buf);
- incref(p);
- sacpathfree(s->path);
- s->path = p;
- return s;
-}
-
-/* n**2 alg to read a directory */
-static int
-sacdirread(Chan *c, uchar *p, long off, long cnt)
-{
- uchar *blocks;
- SacDir *buf;
- int per, i, j, n, ndir;
- long sofar;
- Sac *s;
-
- s = c->aux;
- blocks = data + getl(s->blocks);
- per = blocksize/sizeof(SacDir);
- ndir = getl(s->length);
-
- buf = malloc(blocksize);
- sofar = 0;
- for(j = 0; j < ndir; j++) {
- i = j%per;
- if(i == 0) {
- n = per;
- if(n > ndir-j*per)
- n = ndir-j*per;
- loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
- }
- n = sacdir(c, buf+i, p, cnt - sofar);
- if(n == 0)
- break;
- if(off > 0)
- off -= n;
- else {
- p += n;
- sofar += n;
- }
- }
- free(buf);
-
- return sofar;
-}
-
-static Sac*
-saclookup(Sac *s, char *name)
-{
- int ndir;
- int i, j, k, n, per;
- uchar *blocks;
- SacDir *buf;
- int iblock;
- SacDir *sd;
-
- if(strcmp(name, "..") == 0)
- return sacparent(s);
- blocks = data + getl(s->blocks);
- per = blocksize/sizeof(SacDir);
- ndir = getl(s->length);
- buf = malloc(per*sizeof(SacDir));
- iblock = -1;
-
- // linear search
- for(i=0; i<ndir; i++) {
- j = i/per;
- if(j != iblock) {
- n = per;
- if(n > ndir-j*per)
- n = ndir-j*per;
- loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
- iblock = j;
- }
- j *= per;
- sd = buf+i-j;
- k = strcmp(name, sd->name);
- if(k == 0) {
- s->path = sacpathalloc(s->path, getl(s->blocks), i, ndir);
- s->SacDir = *sd;
- free(buf);
- return s;
- }
- }
- free(buf);
- return 0;
-}
-
-static ulong
-getl(void *p)
-{
- uchar *a = p;
-
- return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
-}
-
-Dev sacdevtab = {
- 'C',
- "sac",
-
- devreset,
- sacinit,
- devshutdown,
- sacattach,
- sacwalk,
- sacstat,
- sacopen,
- devcreate,
- sacclose,
- sacread,
- devbread,
- sacwrite,
- devbwrite,
- devremove,
- devwstat,
-};
D bitsy/unsac.c => bitsy/unsac.c +0 -627
@@ 1,627 0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-typedef struct Huff Huff;
-typedef struct Mtf Mtf;
-typedef struct Decode Decode;
-
-enum
-{
- ZBase = 2, /* base of code to encode 0 runs */
- LitBase = ZBase-1, /* base of literal values */
- MaxLit = 256,
-
- MaxLeaf = MaxLit+LitBase,
- MaxHuffBits = 16, /* max bits in a huffman code */
- MaxFlatbits = 5, /* max bits decoded in flat table */
-
- CombLog = 4,
- CombSpace = 1 << CombLog, /* mtf speedup indices spacing */
- CombMask = CombSpace - 1,
-};
-
-struct Mtf
-{
- int maxcomb; /* index of last valid comb */
- uchar prev[MaxLit];
- uchar next[MaxLit];
- uchar comb[MaxLit / CombSpace + 1];
-};
-
-struct Huff
-{
- int maxbits;
- int flatbits;
- ulong flat[1<<MaxFlatbits];
- ulong maxcode[MaxHuffBits];
- ulong last[MaxHuffBits];
- ulong decode[MaxLeaf];
-};
-
-struct Decode{
- Huff tab;
- Mtf mtf;
- int nbits;
- ulong bits;
- int nzero;
- int base;
- ulong maxblocksym;
-
- uchar *src; /* input buffer */
- uchar *smax; /* limit */
-};
-
-static void fatal(Decode *dec, char*);
-
-static int hdec(Decode*);
-static void recvtab(Decode*, Huff*, int, ushort*);
-static ulong bitget(Decode*, int);
-static int mtf(uchar*, int);
-
-#define FORWARD 0
-
-static void
-mtflistinit(Mtf *m, uchar *front, int n)
-{
- int last, me, f, i, comb;
-
- if(n == 0)
- return;
-
- /*
- * add all entries to free list
- */
- last = MaxLit - 1;
- for(i = 0; i < MaxLit; i++){
- m->prev[i] = last;
- m->next[i] = i + 1;
- last = i;
- }
- m->next[last] = 0;
- f = 0;
-
- /*
- * pull valid entries off free list and enter into mtf list
- */
- comb = 0;
- last = front[0];
- for(i = 0; i < n; i++){
- me = front[i];
-
- f = m->next[me];
- m->prev[f] = m->prev[me];
- m->next[m->prev[f]] = f;
-
- m->next[last] = me;
- m->prev[me] = last;
- last = me;
- if((i & CombMask) == 0)
- m->comb[comb++] = me;
- }
-
- /*
- * pad out the list with dummies to the next comb,
- * using free entries
- */
- for(; i & CombMask; i++){
- me = f;
-
- f = m->next[me];
- m->prev[f] = m->prev[me];
- m->next[m->prev[f]] = f;
-
- m->next[last] = me;
- m->prev[me] = last;
- last = me;
- }
- me = front[0];
- m->next[last] = me;
- m->prev[me] = last;
- m->comb[comb] = me;
- m->maxcomb = comb;
-}
-
-static int
-mtflist(Mtf *m, int pos)
-{
- uchar *next, *prev, *mycomb;
- int c, c0, pc, nc, off;
-
- if(pos == 0)
- return m->comb[0];
-
- next = m->next;
- prev = m->prev;
- mycomb = &m->comb[pos >> CombLog];
- off = pos & CombMask;
- if(off >= CombSpace / 2){
- c = mycomb[1];
- for(; off < CombSpace; off++)
- c = prev[c];
- }else{
- c = *mycomb;
- for(; off; off--)
- c = next[c];
- }
-
- nc = next[c];
- pc = prev[c];
- prev[nc] = pc;
- next[pc] = nc;
-
- for(; mycomb > m->comb; mycomb--)
- *mycomb = prev[*mycomb];
- c0 = *mycomb;
- *mycomb = c;
- mycomb[m->maxcomb] = c;
-
- next[c] = c0;
- pc = prev[c0];
- prev[c] = pc;
- prev[c0] = c;
- next[pc] = c;
- return c;
-}
-
-static void
-hdecblock(Decode *dec, ulong n, ulong I, uchar *buf, ulong *sums, ulong *prev)
-{
- ulong i, nn, sum;
- int m, z, zz, c;
-
- nn = I;
- n--;
- i = 0;
-again:
- for(; i < nn; i++){
- while((m = hdec(dec)) == 0 && i + dec->nzero < n)
- ;
- if(z = dec->nzero){
- dec->nzero = 0;
- c = dec->mtf.comb[0];
- sum = sums[c];
- sums[c] = sum + z;
-
- z += i;
- zz = z;
- if(i < I && z > I){
- zz = I;
- z++;
- }
-
- zagain:
- for(; i < zz; i++){
- buf[i] = c;
- prev[i] = sum++;
- }
- if(i != z){
- zz = z;
- nn = ++n;
- i++;
- goto zagain;
- }
- if(i == nn){
- if(i == n)
- return;
- nn = ++n;
- i++;
- }
- }
-
- c = mtflist(&dec->mtf, m);
-
- buf[i] = c;
- sum = sums[c];
- prev[i] = sum++;
- sums[c] = sum;
-
- }
- if(i == n)
- return;
- nn = ++n;
- i++;
- goto again;
-}
-
-int
-unsac(uchar *dst, uchar *src, int n, int nsrc)
-{
- Decode *dec;
- uchar *buf, *front;
- ulong *prev, *sums;
- ulong sum, i, I;
- int m, j, c;
-
- dec = malloc(sizeof *dec);
- buf = malloc(n+2);
- prev = malloc((n+2) * sizeof *prev);
- front = malloc(MaxLit * sizeof *front);
- sums = malloc(MaxLit * sizeof *sums);
-
- if(waserror()){
- free(dec);
- free(buf);
- free(prev);
- free(front);
- free(sums);
- nexterror();
- }
-
- dec->src = src;
- dec->smax = src + nsrc;
-
- dec->nbits = 0;
- dec->bits = 0;
- dec->nzero = 0;
- for(i = 0; i < MaxLit; i++)
- front[i] = i;
-
- n++;
- I = bitget(dec, 16);
- if(I >= n)
- fatal(dec, "corrupted input");
-
- /*
- * decode the character usage map
- */
- for(i = 0; i < MaxLit; i++)
- sums[i] = 0;
- c = bitget(dec, 1);
- for(i = 0; i < MaxLit; ){
- m = bitget(dec, 8) + 1;
- while(m--){
- if(i >= MaxLit)
- fatal(dec, "corrupted char map");
- front[i++] = c;
- }
- c = c ^ 1;
- }
-
- /*
- * initialize mtf state
- */
- c = 0;
- for(i = 0; i < MaxLit; i++)
- if(front[i])
- front[c++] = i;
- mtflistinit(&dec->mtf, front, c);
- dec->maxblocksym = c + LitBase;
-
- /*
- * huffman decoding, move to front decoding,
- * along with character counting
- */
- dec->base = 1;
- recvtab(dec, &dec->tab, MaxLeaf, nil);
- hdecblock(dec, n, I, buf, sums, prev);
-
- sum = 1;
- for(i = 0; i < MaxLit; i++){
- c = sums[i];
- sums[i] = sum;
- sum += c;
- }
-
- i = 0;
- for(j = n - 2; j >= 0; j--){
- if(i > n || i < 0 || i == I)
- fatal(dec, "corrupted data");
- c = buf[i];
- dst[j] = c;
- i = prev[i] + sums[c];
- }
-
- poperror();
-
- free(dec);
- free(buf);
- free(prev);
- free(front);
- free(sums);
- return n;
-}
-
-static ulong
-bitget(Decode *dec, int nb)
-{
- int c;
-
- while(dec->nbits < nb){
- if(dec->src >= dec->smax)
- fatal(dec, "premature eof 1");
- c = *dec->src++;
- dec->bits <<= 8;
- dec->bits |= c;
- dec->nbits += 8;
- }
- dec->nbits -= nb;
- return (dec->bits >> dec->nbits) & ((1 << nb) - 1);
-}
-
-static void
-fillbits(Decode *dec)
-{
- int c;
-
- while(dec->nbits < 24){
- if(dec->src >= dec->smax)
- fatal(dec, "premature eof 2");
- c = *dec->src++;
- dec->bits <<= 8;
- dec->bits |= c;
- dec->nbits += 8;
- }
-}
-
-/*
- * decode one symbol
- */
-static int
-hdecsym(Decode *dec, Huff *h, int b)
-{
- long c;
- ulong bits;
- int nbits;
-
- bits = dec->bits;
- nbits = dec->nbits;
- for(; (c = bits >> (nbits - b)) > h->maxcode[b]; b++)
- ;
- if(b > h->maxbits)
- fatal(dec, "too many bits consumed");
- dec->nbits = nbits - b;
- return h->decode[h->last[b] - c];
-}
-
-static int
-hdec(Decode *dec)
-{
- ulong c;
- int nbits, nb;
-
- if(dec->nbits < dec->tab.maxbits)
- fillbits(dec);
- nbits = dec->nbits;
- dec->bits &= (1 << nbits) - 1;
- c = dec->tab.flat[dec->bits >> (nbits - dec->tab.flatbits)];
- nb = c & 0xff;
- c >>= 8;
- if(nb == 0xff)
- c = hdecsym(dec, &dec->tab, c);
- else
- dec->nbits = nbits - nb;
-
- /*
- * reverse funny run-length coding
- */
- if(c < ZBase){
- dec->nzero += dec->base << c;
- dec->base <<= 1;
- return 0;
- }
-
- dec->base = 1;
- c -= LitBase;
- return c;
-}
-
-static void
-hufftab(Decode *dec, Huff *h, char *hb, ulong *bitcount, int maxleaf, int maxbits, int flatbits)
-{
- ulong c, mincode, code, nc[MaxHuffBits];
- int i, b, ec;
-
- h->maxbits = maxbits;
- if(maxbits < 0)
- return;
-
- code = 0;
- c = 0;
- for(b = 0; b <= maxbits; b++){
- h->last[b] = c;
- c += bitcount[b];
- mincode = code << 1;
- nc[b] = mincode;
- code = mincode + bitcount[b];
- if(code > (1 << b))
- fatal(dec, "corrupted huffman table");
- h->maxcode[b] = code - 1;
- h->last[b] += code - 1;
- }
- if(code != (1 << maxbits))
- fatal(dec, "huffman table not full");
- if(flatbits > maxbits)
- flatbits = maxbits;
- h->flatbits = flatbits;
-
- b = 1 << flatbits;
- for(i = 0; i < b; i++)
- h->flat[i] = ~0;
-
- /*
- * initialize the flat table to include the minimum possible
- * bit length for each code prefix
- */
- for(b = maxbits; b > flatbits; b--){
- code = h->maxcode[b];
- if(code == -1)
- break;
- mincode = code + 1 - bitcount[b];
- mincode >>= b - flatbits;
- code >>= b - flatbits;
- for(; mincode <= code; mincode++)
- h->flat[mincode] = (b << 8) | 0xff;
- }
-
- for(i = 0; i < maxleaf; i++){
- b = hb[i];
- if(b == -1)
- continue;
- c = nc[b]++;
- if(b <= flatbits){
- code = (i << 8) | b;
- ec = (c + 1) << (flatbits - b);
- if(ec > (1<<flatbits))
- fatal(dec, "flat code too big");
- for(c <<= (flatbits - b); c < ec; c++)
- h->flat[c] = code;
- }else{
- c = h->last[b] - c;
- if(c >= maxleaf)
- fatal(dec, "corrupted huffman table");
- h->decode[c] = i;
- }
- }
-}
-
-static void
-elimBit(int b, char *tmtf, int maxbits)
-{
- int bb;
-
- for(bb = 0; bb < maxbits; bb++)
- if(tmtf[bb] == b)
- break;
- while(++bb <= maxbits)
- tmtf[bb - 1] = tmtf[bb];
-}
-
-static int
-elimBits(int b, ulong *bused, char *tmtf, int maxbits)
-{
- int bb, elim;
-
- if(b < 0)
- return 0;
-
- elim = 0;
-
- /*
- * increase bits counts for all descendants
- */
- for(bb = b + 1; bb < maxbits; bb++){
- bused[bb] += 1 << (bb - b);
- if(bused[bb] == (1 << bb)){
- elim++;
- elimBit(bb, tmtf, maxbits);
- }
- }
-
- /*
- * steal bits from parent & check for fullness
- */
- for(; b >= 0; b--){
- bused[b]++;
- if(bused[b] == (1 << b)){
- elim++;
- elimBit(b, tmtf, maxbits);
- }
- if((bused[b] & 1) == 0)
- break;
- }
- return elim;
-}
-
-static void
-recvtab(Decode *dec, Huff *tab, int maxleaf, ushort *map)
-{
- ulong bitcount[MaxHuffBits+1], bused[MaxHuffBits+1];
- char tmtf[MaxHuffBits+1], *hb;
- int i, b, ttb, m, maxbits, max, elim;
-
- hb = malloc(MaxLeaf * sizeof *hb);
- if(waserror()) {
- free(hb);
- nexterror();
- }
-
- /*
- * read the tables for the tables
- */
- max = 8;
- for(i = 0; i <= MaxHuffBits; i++){
- bitcount[i] = 0;
- tmtf[i] = i;
- bused[i] = 0;
- }
- tmtf[0] = -1;
- tmtf[max] = 0;
- elim = 0;
- maxbits = -1;
- for(i = 0; i <= MaxHuffBits && elim != max; i++){
- ttb = 4;
- while(max - elim < (1 << (ttb-1)))
- ttb--;
- b = bitget(dec, ttb);
- if(b > max - elim)
- fatal(dec, "corrupted huffman table table");
- b = tmtf[b];
- hb[i] = b;
- bitcount[b]++;
- if(b > maxbits)
- maxbits = b;
-
- elim += elimBits(b, bused, tmtf, max);
- }
- if(elim != max)
- fatal(dec, "incomplete huffman table table");
- hufftab(dec, tab, hb, bitcount, i, maxbits, MaxFlatbits);
- for(i = 0; i <= MaxHuffBits; i++){
- tmtf[i] = i;
- bitcount[i] = 0;
- bused[i] = 0;
- }
- tmtf[0] = -1;
- tmtf[MaxHuffBits] = 0;
- elim = 0;
- maxbits = -1;
- for(i = 0; i < maxleaf && elim != MaxHuffBits; i++){
- if(dec->nbits <= tab->maxbits)
- fillbits(dec);
- dec->bits &= (1 << dec->nbits) - 1;
- m = tab->flat[dec->bits >> (dec->nbits - tab->flatbits)];
- b = m & 0xff;
- m >>= 8;
- if(b == 0xff)
- m = hdecsym(dec, tab, m);
- else
- dec->nbits -= b;
- b = tmtf[m];
- for(; m > 0; m--)
- tmtf[m] = tmtf[m-1];
- tmtf[0] = b;
-
- if(b > MaxHuffBits)
- fatal(dec, "bit length too big");
- m = i;
- if(map != nil)
- m = map[m];
- hb[m] = b;
- bitcount[b]++;
- if(b > maxbits)
- maxbits = b;
- elim += elimBits(b, bused, tmtf, MaxHuffBits);
- }
- if(elim != MaxHuffBits && elim != 0)
- fatal(dec, "incomplete huffman table");
- if(map != nil)
- for(; i < maxleaf; i++)
- hb[map[i]] = -1;
-
- hufftab(dec, tab, hb, bitcount, i, maxbits, MaxFlatbits);
-
- poperror();
- free(hb);
-}
-
-static void
-fatal(Decode *dec, char *msg)
-{
- USED(dec);
-print("unsac: %s\n", msg);
- error(msg);
-}
M pc/devarch.c => pc/devarch.c +3 -0
@@ 791,6 791,9 @@ archinit(void)
if(X86FAMILY(m->cpuidax) == 3)
conf.copymode = 1;
+// if(X86FAMILY(m->cpuidax) >= 5 && conf.nmach > 1)
+ coherence = wbflush;
+
addarchfile("cputype", 0444, cputyperead, nil);
addarchfile("pge", 0664, pgeread, pgewrite);
}
M pc/fns.h => pc/fns.h +2 -1
@@ 10,7 10,6 @@ int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
#define clearmmucache() /* x86 doesn't have one */
void clockintr(Ureg*, void*);
-void clockintrsched(void);
void (*coherence)(void);
void cpuid(char*, int*, int*);
int cpuidentify(void);
@@ 126,6 125,7 @@ void rdtsc(vlong*);
void screeninit(void);
int screenprint(char*, ...); /* debugging */
void (*screenputs)(char*, int);
+void sfence(void);
void touser(void*);
void trapenable(int, void (*)(Ureg*, void*), void*, char*);
void trapinit(void);
@@ 140,6 140,7 @@ void upafree(ulong, int);
void vectortable(void);
void wrmsr(int, vlong);
void wbflush(void);
+void wbinvd(void);
int xchgw(ushort*, int);
ulong TK2MS(ulong); /* ticks to milliseconds */
M pc/l.s => pc/l.s +15 -0
@@ 14,6 14,7 @@
#define RDTSC BYTE $0x0F; BYTE $0x31
#define WBINVD BYTE $0x0F; BYTE $0x09
#define HLT BYTE $0xF4
+#define SFENCE BYTE $0x0F; BYTE $0xAE; BYTE $0xF8
/*
* Macros for calculating offsets within the page directory base
@@ 303,6 304,10 @@ TEXT wbinvd(SB), $0
WBINVD
RET
+TEXT sfence(SB), $0
+ SFENCE
+ RET
+
/*
* Try to determine the CPU type which requires fiddling with EFLAGS.
* If the Id bit can be toggled then the CPUID instruciton can be used
@@ 498,6 503,16 @@ TEXT gotolabel(SB), $0
MOVL $1, AX /* return 1 */
RET
+TEXT swaplabel(SB), $0
+ MOVL label+0(FP), AX
+ MOVL pc+4(FP), BX
+ MOVL 0(AX), SP /* restore sp */
+ MOVL 4(AX), CX /* put return pc on the stack */
+ MOVL CX, 0(SP)
+ MOVL BX, 4(AX) /* put caller pc where return pc was */
+ MOVL $1, AX /* return 1 */
+ RET
+
TEXT setlabel(SB), $0
MOVL label+0(FP), AX
MOVL SP, 0(AX) /* store sp */
M port/devloopback.c => port/devloopback.c +0 -1
@@ 597,7 597,6 @@ looper(Loop *lb)
t = fastticks(nil);
for(chan = 0; chan < 2; chan++)
pushlink(&lb->link[chan], t);
- clockintrsched();
}
static void
M port/devtls.c => port/devtls.c +2 -2
@@ 760,8 760,8 @@ tlsrecread(TlsRec *tr)
len = get16(header+3);
}
if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
- rcvError(tr, EProtocolVersion, "record layer saw ver %x, not %x/%d; %d %d",
- ver, tr->version, tr->verset, type, len);
+ rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
+ tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
if(len > MaxCipherRecLen || len < 0)
rcvError(tr, ERecordOverflow, "record message too long %d", len);
ensure(tr, &tr->unprocessed, len);
M port/nulledf.c => port/nulledf.c +5 -5
@@ 13,29 13,29 @@ isedf(Proc*)
}
void
-edf_bury(Proc*)
+edfbury(Proc*)
{
}
int
-edf_anyready(void)
+edfanyready(void)
{
return 0;
}
void
-edf_ready(Proc*)
+edfready(Proc*)
{
}
Proc*
-edf_runproc(void)
+edfrunproc(void)
{
return nil;
}
void
-edf_block(Proc*)
+edfblock(Proc*)
{
}
M port/portclock.c => port/portclock.c +9 -11
@@ 96,10 96,6 @@ hzclock(Ureg *ur)
if(m->proc)
m->proc->pc = ur->pc;
- if(m->inclockintr)
- return; /* interrupted ourself */
- m->inclockintr = 1;
-
if(m->flushmmu){
if(up)
flushmmu();
@@ 148,10 144,14 @@ timerintr(Ureg *u, uvlong)
uvlong when, now;
int callhzclock;
+ if(m->inclockintr)
+ return;
+ m->inclockintr = 1;
+
intrcount[m->machno]++;
callhzclock = 0;
tt = &timers[m->machno];
- now = (uvlong)fastticks(nil);
+ now = fastticks(nil);
ilock(tt);
while(t = tt->head){
when = t->when;
@@ 160,6 160,7 @@ timerintr(Ureg *u, uvlong)
timerset(when);
if(callhzclock)
hzclock(u);
+ m->inclockintr = 0;
return;
}
tt->head = t->next;
@@ 179,6 180,7 @@ timerintr(Ureg *u, uvlong)
}
}
iunlock(tt);
+ m->inclockintr = 0;
}
uvlong hzperiod;
@@ 190,7 192,8 @@ timersinit(void)
hzperiod = ms2fastticks(1000/HZ);
- t = smalloc(sizeof(*t));
+ t = malloc(sizeof(*t));
+ t->when = 0;
t->period = hzperiod;
t->f = nil;
timeradd(t);
@@ 216,8 219,3 @@ addclock0link(void (*f)(void))
*/
iunlock(&timers[0]);
}
-
-void
-clockintrsched(void)
-{
-}
M port/proc.c => port/proc.c +1 -0
@@ 1146,6 1146,7 @@ error(char *err)
{
spllo();
kstrcpy(up->errstr, err, ERRMAX);
+ setlabel(&up->errlab[NERR-1]);
nexterror();
}
M port/taslock.c => port/taslock.c +9 -4
@@ 152,6 152,7 @@ canlock(Lock *l)
return 1;
}
+int buggeredsched;
void
unlock(Lock *l)
{
@@ 165,11 166,15 @@ unlock(Lock *l)
coherence();
/* give up the processor if ... */
- if(up && --up->nlocks == 0 /* we've closed the last nexted lock */
+ if(up && --up->nlocks == 0 /* we've closed the last nested lock */
&& up->delaysched /* we delayed scheduling because of the lock */
- && up->state == Running){ /* we're in running state */
- up->delaysched = 0;
- sched();
+ && up->state == Running){ /* we're in running state */
+ if(!islo())
+ buggeredsched++;
+ else{
+ up->delaysched = 0;
+ sched();
+ }
}
}