M boot/boot.c => boot/boot.c +48 -1
@@ 25,6 25,51 @@ static void recover(Method*);
static Method *rootserver(char*);
void
+ethertest(void)
+{
+ int cf, df, n, t;
+ char buf[64];
+ struct Etherpkt
+ {
+ uchar d[6];
+ uchar s[6];
+ uchar type[2];
+ } p;
+
+ cf = open("#l/ether/clone", ORDWR);
+ if(cf < 0){
+ print("can't open #l/ether/clone: %r\n");
+ exits(0);
+ }
+ n = read(cf, buf, 12);
+ if(n < 0){
+ print("can't read #l/ether/clone: %r\n");
+ exits(0);
+ }
+ buf[n] = 0;
+ sprint(buf, "#l/ether/%d/data", atoi(buf));
+ df = open(buf, ORDWR);
+ if(df < 0){
+ print("can't open %s: %r\n", buf);
+ exits(0);
+ }
+ if(write(cf, "connect -1", sizeof("connect -1")-1) < 0){
+ print("can't connect -1: %r\n");
+ exits(0);
+ }
+ close(cf);
+ for(;;){
+ n = read(df, &p, sizeof(p));
+ if(n <= 0){
+ print("read returns %d: %r\n", n);
+ continue;
+ }
+ t = (p.type[0]<<8) | p.type[1];
+ print("%d %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux -> %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux %ux\n", n, p.s[0], p.s[1], p.s[2], p.s[3], p.s[4], p.s[5], p.d[0], p.d[1], p.d[2], p.d[3], p.d[4], p.d[5], t);
+ }
+}
+
+void
boot(int argc, char *argv[])
{
int fd;
@@ 38,11 83,13 @@ boot(int argc, char *argv[])
open("#c/cons", OREAD);
open("#c/cons", OWRITE);
open("#c/cons", OWRITE);
-/* print("argc=%d\n", argc);
+ print("argc=%d\n", argc);
for(fd = 0; fd < argc; fd++)
print("%s ", argv[fd]);
print("\n");/**/
+ ethertest();
+
if(argc <= 1)
pflag = 1;
M port/dev.c => port/dev.c +1 -1
@@ 149,7 149,7 @@ devstat(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen)
* by namec.
*/
if(c->qid.path & CHDIR){
- devdir(c, c->qid, c->path->elem, i*DIRLEN, eve, CHDIR|0700, &dir);
+ devdir(c, c->qid, c->path->elem, i*DIRLEN, eve, CHDIR|0555, &dir);
convD2M(&dir, db);
return;
}
A port/netif.c => port/netif.c +378 -0
@@ 0,0 1,378 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+uchar etherbcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static int netown(Netfile*, char*, int);
+static int openfile(Netif*, int);
+static char* matchtoken(char*, char*);
+
+/*
+ * set up a new network interface
+ */
+void
+netifinit(Netif *nif, char *name, int nfile, ulong limit)
+{
+ nif->name = name;
+ nif->nfile = nfile;
+ nif->f = xalloc(nfile*sizeof(Netfile*));
+ memset(nif->f, 0, nfile*sizeof(Netfile*));
+ nif->limit = limit;
+ nif->out = qopen(limit, 0, 0);
+}
+
+/*
+ * generate a 3 level directory
+ */
+static int
+netifgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
+{
+ Qid q;
+ char buf[32];
+ Netif *nif = vp;
+ Netfile *f;
+ int t;
+ int perm;
+ char *o;
+
+ USED(ntab);
+ q.vers = 0;
+
+ /* top level directory contains the name of the network */
+ if(c->qid.path == CHDIR){
+ switch(i){
+ case 0:
+ q.path = CHDIR | N2ndqid;
+ strcpy(buf, nif->name);
+ devdir(c, q, buf, 0, eve, 0555, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ /* second level contains clone plus all the conversations */
+ t = NETTYPE(c->qid.path);
+ if(t == N2ndqid || t == Ncloneqid){
+ if(i == 0){
+ q.path = Ncloneqid;
+ devdir(c, q, "clone", 0, eve, 0666, dp);
+ }else if(i <= nif->nfile){
+ if(nif->f[i-1] == 0)
+ return 0;
+ q.path = CHDIR|NETQID(i-1, N3rdqid);
+ sprint(buf, "%d", i-1);
+ devdir(c, q, buf, 0, eve, 0555, dp);
+ }else
+ return -1;
+ return 1;
+ }
+
+ /* third level */
+ f = nif->f[NETID(c->qid.path)];
+ if(f == 0)
+ return 0;
+ if(*f->owner){
+ o = f->owner;
+ perm = f->mode;
+ } else {
+ o = eve;
+ perm = 0666;
+ }
+ switch(i){
+ case 0:
+ q.path = NETQID(NETID(c->qid.path), Ndataqid);
+ devdir(c, q, "data", 0, o, perm, dp);
+ break;
+ case 1:
+ q.path = NETQID(NETID(c->qid.path), Nctlqid);
+ devdir(c, q, "ctl", 0, o, perm, dp);
+ break;
+ case 2:
+ q.path = NETQID(NETID(c->qid.path), Nstatqid);
+ devdir(c, q, "stat", 0, eve, 0444, dp);
+ break;
+ case 3:
+ q.path = NETQID(NETID(c->qid.path), Ntypeqid);
+ devdir(c, q, "type", 0, eve, 0444, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+}
+
+int
+netifwalk(Netif *nif, Chan *c, char *name)
+{
+ return devwalk(c, name, (Dirtab *)nif, 0, netifgen);
+}
+
+Chan*
+netifopen(Netif *nif, Chan *c, int omode)
+{
+ int id = 0;
+ Netfile *f;
+
+ if(c->qid.path & CHDIR){
+ if(omode != OREAD)
+ error(Eperm);
+ } else {
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ id = NETID(c->qid.path);
+ openfile(nif, id);
+ break;
+ case Ncloneqid:
+ id = openfile(nif, -1);
+ c->qid.path = NETQID(id, Nctlqid);
+ ptclone(c, 0, id);
+ break;
+ default:
+ if(omode != OREAD)
+ error(Ebadarg);
+ }
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ f = nif->f[id];
+ if(netown(f, up->user, omode&7) < 0)
+ error(Eperm);
+ break;
+ }
+ }
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+long
+netifread(Netif *nif, Chan *c, void *a, long n, ulong offset)
+{
+ Netfile *f;
+ int i;
+ char buf[256];
+
+ if(c->qid.path&CHDIR)
+ return devdirread(c, a, n, (Dirtab*)nif, 0, netifgen);
+
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ f = nif->f[NETID(c->qid.path)];
+ return qread(f->in, a, n);
+ case Nctlqid:
+ return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
+ case Nstatqid:
+ n = sprint(buf, "in: %d\n", nif->inpackets);
+ n += sprint(buf+n, "out: %d\n", nif->outpackets);
+ n += sprint(buf+n, "crc errs: %d\n", nif->crcs);
+ n += sprint(buf+n, "overflows: %d\n", nif->overflows);
+ n += sprint(buf+n, "framing errs: %d\n", nif->frames);
+ n += sprint(buf+n, "buffer errs: %d\n", nif->buffs);
+ n += sprint(buf+n, "output errs: %d\n", nif->oerrs);
+ n += sprint(buf+n, "addr:", nif->oerrs);
+ for(i = 0; i < nif->alen; i++)
+ n += sprint(buf+n, "%2.2ux", nif->addr[i]);
+ n += sprint(buf+n, "\n");
+ return readstr(offset, a, n, buf);
+ case Ntypeqid:
+ f = nif->f[NETID(c->qid.path)];
+ return readnum(offset, a, n, f->type, NUMSIZE);
+ }
+ error(Ebadarg);
+ return -1; /* not reached */
+}
+
+/*
+ * the devxxx.c that calls us handles writing data, it knows best
+ */
+long
+netifwrite(Netif *nif, Chan *c, void *a, long n)
+{
+ Netfile *f;
+ char *p;
+ char buf[256];
+
+ if(NETTYPE(c->qid.path) != Nctlqid)
+ error(Eperm);
+
+ if(n >= sizeof(buf))
+ n = sizeof(buf)-1;
+ memmove(buf, a, n);
+ buf[n] = 0;
+
+ qlock(nif);
+ f = nif->f[NETID(c->qid.path)];
+ if(p = matchtoken(buf, "connect")){
+ f->type = atoi(p);
+ } else if(matchtoken(buf, "promiscuous")){
+ f->prom = 1;
+ nif->prom++;
+ if(nif->prom == 1)
+ (*nif->promiscuous)(nif->arg, 1);
+ }
+ qunlock(nif);
+ return n;
+}
+
+void
+netifwstat(Netif *nif, Chan *c, char *db)
+{
+ Dir dir;
+ Netfile *f;
+
+ f = nif->f[NETID(c->qid.path)];
+ if(f == 0)
+ error(Enonexist);
+
+ if(netown(f, up->user, OWRITE) < 0)
+ error(Eperm);
+
+ convM2D(db, &dir);
+ strncpy(f->owner, dir.uid, NAMELEN);
+ f->mode = dir.mode;
+}
+
+void
+netifstat(Netif *nif, Chan *c, char *db)
+{
+
+ devstat(c, db, (Dirtab *)nif, 0, netifgen);
+}
+
+void
+netifclose(Netif *nif, Chan *c)
+{
+ Netfile *f;
+ int t;
+
+ t = NETTYPE(c->qid.path);
+ if(t != Ndataqid && t != Nctlqid)
+ return;
+
+ f = nif->f[NETID(c->qid.path)];
+ qlock(f);
+ if(--(f->inuse) == 0){
+ if(f->prom){
+ qlock(nif);
+ if(--(nif->prom) == 0)
+ (*nif->promiscuous)(nif->arg, 0);
+ qunlock(nif);
+ }
+ f->owner[0] = 0;
+ }
+ qunlock(f);
+}
+
+Lock netlock;
+
+static int
+netown(Netfile *p, char *o, int omode)
+{
+ static int access[] = { 0400, 0200, 0600, 0100 };
+ int mode;
+ int t;
+
+ lock(&netlock);
+ if(*p->owner){
+ if(strncmp(o, p->owner, NAMELEN) == 0) /* User */
+ mode = p->mode;
+ else if(strncmp(o, eve, NAMELEN) == 0) /* Bootes is group */
+ mode = p->mode<<3;
+ else
+ mode = p->mode<<6; /* Other */
+
+ t = access[omode&3];
+ if((t & mode) == t){
+ unlock(&netlock);
+ return 0;
+ } else {
+ unlock(&netlock);
+ return -1;
+ }
+ }
+ strncpy(p->owner, o, NAMELEN);
+ p->mode = 0660;
+ unlock(&netlock);
+ return 0;
+}
+
+/*
+ * Increment the reference count of a network device.
+ * If id < 0, return an unused ether device.
+ */
+static int
+openfile(Netif *nif, int id)
+{
+ Netfile *f, **fp, **efp;
+
+ if(id >= 0){
+ f = nif->f[id];
+ if(f == 0)
+ error(Enodev);
+ qlock(f);
+ f->inuse++;
+ qunlock(f);
+ return id;
+ }
+
+ qlock(nif);
+ efp = &nif->f[nif->nfile];
+ for(fp = nif->f; fp < efp; fp++){
+ f = *fp;
+ if(f == 0){
+ f = malloc(sizeof(Netfile));
+ if(f == 0){
+ qunlock(nif);
+ error(Enodev);
+ }
+ *fp = f;
+ f->in = qopen(nif->limit, 0, 0);
+ qlock(f);
+ } else {
+ qlock(f);
+ if(f->inuse){
+ qunlock(f);
+ continue;
+ }
+ }
+ f->inuse = 1;
+ netown(f, up->user, 0);
+ qunlock(f);
+ qunlock(nif);
+ return fp - nif->f;
+ }
+ qunlock(nif);
+ error(Enodev);
+ return -1; /* not reached */
+}
+
+/*
+ * look for a token starting a string, return a pointer to first non-space char after it
+ */
+static char*
+matchtoken(char *p, char *token)
+{
+ int n;
+
+ n = strlen(token);
+ if(strncmp(p, token, n))
+ return 0;
+ p += n;
+ if(*p == 0)
+ return p;
+ if(*p != ' ' && *p != '\t' && *p != '\n')
+ return 0;
+ while(*p == ' ' || *p == '\t' || *p == '\n')
+ p++;
+ return p;
+}
A port/netif.h => port/netif.h +109 -0
@@ 0,0 1,109 @@
+typedef struct Etherpkt Etherpkt;
+typedef struct Netfile Netfile;
+typedef struct Netif Netif;
+
+enum
+{
+ Nmaxaddr= 64,
+
+ Ncloneqid= 1,
+ N2ndqid,
+ N3rdqid,
+ Ndataqid,
+ Nctlqid,
+ Nstatqid,
+ Ntypeqid,
+};
+
+/*
+ * Macros to manage Qid's used for multiplexed devices
+ */
+#define NETTYPE(x) ((x)&0x1f)
+#define NETID(x) (((x)&~CHDIR)>>5)
+#define NETQID(i,t) (((i)<<5)|(t))
+
+/*
+ * one per multiplexed connection
+ */
+struct Netfile
+{
+ QLock;
+
+ int inuse;
+ ulong mode;
+ char owner[NAMELEN];
+
+ int type; /* multiplexor type */
+ int prom; /* promiscuous mode */
+
+ Queue *in; /* input buffer */
+};
+
+/*
+ * a network interface
+ */
+struct Netif
+{
+ QLock;
+
+ /* multiplexing */
+ char *name; /* for top level directory */
+ int nfile; /* max number of Netfiles */
+ Netfile **f;
+ Queue *out; /* output buffer */
+
+ /* about net */
+ int limit; /* flow control */
+ int alen; /* address length */
+ uchar addr[Nmaxaddr];
+ uchar bcast[Nmaxaddr];
+ int prom;
+
+ /* statistics */
+ int misses;
+ int inpackets;
+ int outpackets;
+ int crcs; /* input crc errors */
+ int oerrs; /* output erros */
+ int frames; /* framing errors */
+ int overflows; /* packet overflows */
+ int buffs; /* buffering errors */
+
+ /* routines for touching the hardware */
+ void *arg;
+ void (*promiscuous)(void*, int);
+};
+
+void netifinit(Netif*, char*, int, ulong);
+int netifwalk(Netif*, Chan*, char*);
+Chan* netifopen(Netif*, Chan*, int);
+void netifclose(Netif*, Chan*);
+long netifread(Netif*, Chan*, void*, long, ulong);
+long netifwrite(Netif*, Chan*, void*, long);
+void netifwstat(Netif*, Chan*, char*);
+void netifstat(Netif*, Chan*, char*);
+
+/*
+ * Ethernet specific
+ */
+enum
+{
+ Eaddrlen= 6,
+ ETHERMINTU = 60, /* minimum transmit size */
+ ETHERMAXTU = 1514, /* maximum transmit size */
+ ETHERHDRSIZE = 14, /* size of an ethernet header */
+};
+
+struct Etherpkt
+{
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
+};
+
+extern uchar etherbcast[6];
+
+/*
+ * FDDI specific
+ */
M port/portdat.h => port/portdat.h +1 -47
@@ 16,9 16,6 @@ typedef struct Mntrpc Mntrpc;
typedef struct Mntwalk Mntwalk;
typedef struct Mnt Mnt;
typedef struct Mhead Mhead;
-typedef struct Netinf Netinf;
-typedef struct Netprot Netprot;
-typedef struct Network Network;
typedef struct Note Note;
typedef struct Page Page;
typedef struct Path Path;
@@ 678,53 675,10 @@ struct Queue
enum
{
Qstarve=1, /* consumer starved */
+ Qmsg=1, /* message oriented */
};
#define BLEN(b) ((b)->wp - (b)->rp)
-/*
- * Macros to manage Qid's used for multiplexed devices
- */
-#define NETTYPE(x) ((x)&0x1f)
-#define NETID(x) (((x)&~CHDIR)>>5)
-#define NETQID(i,t) (((i)<<5)|(t))
-enum
-{
- Nhighqid = NETQID(1,0) - 1,
- Ndataqid = Nhighqid,
- Nctlqid = Ndataqid-1,
- Nlowqid = Nctlqid,
-};
-
-/*
- * a multiplexed network
- */
-struct Netprot
-{
- int id;
- Netprot *next; /* linked list of protections */
- ulong mode;
- char owner[NAMELEN];
- Network *net;
-};
-
-struct Netinf
-{
- char *name;
- void (*fill)(Netprot*, char*, int);
-};
-
-struct Network
-{
- Lock;
- char *name;
- int nconv; /* max # of conversations */
- int (*listen)(Netprot*);
- int (*open)(Netprot*, int);
- int ninfo;
- Netinf info[5];
- Netprot *prot; /* linked list of protections */
- void *ptr;
-};
enum
{
M port/portfns.h => port/portfns.h +3 -12
@@ 127,15 127,6 @@ void mousescreenupdate(void);
int msize(void*);
Chan* namec(char*, int, int, ulong);
void nameok(char*);
-void netdisown(Netprot*);
-int netgen(Chan*, void*, int, int, Dir*);
-Chan* netopen(Chan*, int, Network*);
-int netown(Netprot*, char*, int);
-void netadd(Network*, Netprot*, int);
-long netread(Chan*, void*, long, ulong, Network*);
-void netstat(Chan*, char*, Network*);
-int netwalk(Chan*, char*, Network*);
-void netwstat(Chan*, char*, Network*);
Chan* newchan(void);
Mount* newmount(Mhead*, Chan*, int, char*);
Page* newpage(int, Segment **, ulong);
@@ 178,10 169,10 @@ void putstr(char*);
void putstrn(char*, long);
void putswap(Page*);
ulong pwait(Waitmsg*);
-int qconsume(Queue*, uchar*, int, int);
+int qconsume(Queue*, uchar*, int);
void qlock(QLock*);
-Queue* qopen(int);
-int qproduce(Queue*, uchar*, int, int);
+Queue* qopen(int, void (*)(void*), void*);
+int qproduce(Queue*, uchar*, int);
long qread(Queue*, char*, int, int);
void qunlock(QLock*);
long qwrite(Queue*, char*, int);
M port/stream.c => port/stream.c +69 -46
@@ 1,3 1,4 @@
+#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
@@ 19,19 20,20 @@ struct Chunk
Chunk *next;
};
-struct Alloc
+struct Chunkl
{
Lock;
Chunk *first;
- int had;
+ int have;
int goal;
- int last;
+ int hist;
};
struct Arena
{
- Chunkl alloc[Maxpow-Minpow+1];
+ Chunkl alloc[Maxpow+1];
Chunkl freed;
+ Rendez r;
};
static Arena arena;
@@ 48,17 50,17 @@ iallockproc(void *arg)
USED(arg);
for(;;){
- tsleep(&freed->r, return0, 0, 500);
+ tsleep(&arena.r, return0, 0, 500);
/* really free what was freed at interrupt level */
cl = &arena.freed;
if(cl->first){
- x = slphi();
+ x = splhi();
lock(cl);
first = cl->first;
cl->first = 0;
unlock(cl);
- spllo();
+ splx(x);
for(; first; first = p){
p = first->next;
@@ 69,10 71,18 @@ iallockproc(void *arg)
/* make sure we have blocks available for interrupt level */
for(pow = Minpow; pow <= Maxpow; pow++){
cl = &arena.alloc[pow];
+
+ /*
+ * if we've been ahead of the game for a while
+ * start giving blocks back to the general pool
+ */
if(cl->have >= cl->goal){
- cl->had = cl->have;
+ cl->hist = ((cl->hist<<1) | 1) & 0xff;
+ if(cl->hist == 0xff && cl->goal > 8)
+ cl->goal--;
continue;
- }
+ } else
+ cl->hist <<= 1;
/*
* increase goal if we've been drained, decrease
@@ 80,13 90,8 @@ iallockproc(void *arg)
*/
if(cl->have == 0)
cl->goal += cl->goal>>2;
- else {
- x = cl->goal/2;
- if(cl->goal > 4 && cl->had > x && cl->have > x)
- cl->goal--;
- }
- cl->had = cl->have;
+ first = 0;
l = &first;
for(i = x = cl->goal - cl->have; x > 0; x--){
p = malloc(1<<pow);
@@ 102,7 107,7 @@ iallockproc(void *arg)
cl->first = first;
cl->have += i;
unlock(cl);
- spllo(x);
+ splx(x);
}
}
}
@@ 130,7 135,7 @@ ialloc(int size)
Chunkl *cl;
Chunk *p;
- for(pow = Min; pow <= Maxpow; pow++)
+ for(pow = Minpow; pow <= Maxpow; pow++)
if(size <= (1<<pow)){
cl = &arena.alloc[pow];
lock(cl);
@@ 143,6 148,7 @@ ialloc(int size)
return (void*)p;
}
panic("ialloc %d\n", size);
+ return 0; /* not reached */
}
void
@@ 183,7 189,7 @@ allocb(int size)
* set, any bytes left in a block afer a consume are discarded.
*/
int
-consume(Queue *q, uchar *p, int len, int drop)
+qconsume(Queue *q, uchar *p, int len)
{
Block *b;
int n;
@@ 199,28 205,29 @@ consume(Queue *q, uchar *p, int len, int drop)
if(n < len)
len = n;
memmove(p, b->rp, len);
- if(drop || len == n)
+ if((q->state&Qmsg) || len == n)
q->bfirst = b->next;
else
b->rp += len;
q->len -= len;
- /* wakeup flow controlled writers */
- if(q->len+len >= q->limit && q->len < q->limit)
+ /* wakeup flow controlled writers (with a bit of histeresis) */
+ if(q->len+len >= q->limit && q->len < q->limit/2)
wakeup(&q->r);
unlock(q);
- if(drop || len == n)
+ if((q->state&Qmsg) || len == n)
ifree(b);
return len;
}
int
-produce(Queue *q, uchar *p, int len, int append)
+qproduce(Queue *q, uchar *p, int len)
{
Block *b;
+ int n;
lock(q);
b = q->rfirst;
@@ 237,17 244,23 @@ produce(Queue *q, uchar *p, int len, int append)
return len;
}
- /* no waiting receivers, buffer */
- if(q->len >= q->limit)
+ /* no waiting receivers, room in buffer? */
+ if(q->len >= q->limit){
+ unlock(q);
return -1;
- b = q->first;
- if(append && b && b->lim-b->wp <= len){
+ }
+
+ /* save in buffer */
+ b = q->bfirst;
+ if((q->state&Qmsg)==0 && b && b->lim-b->wp <= len){
memmove(b->wp, p, len);
b->wp += len;
} else {
b = ialloc(sizeof(Block)+len);
- if(b == 0)
+ if(b == 0){
+ unlock(q);
return -1;
+ }
b->base = (uchar*)(b+1);
b->rp = b->base;
b->wp = b->lim = b->base + len;
@@ 256,7 269,7 @@ produce(Queue *q, uchar *p, int len, int append)
q->blast->next = b;
else
q->bfirst = b;
- q->last = b;
+ q->blast = b;
}
q->len += len;
unlock(q);
@@ 277,6 290,9 @@ qopen(int limit, void (*kick)(void*), void *arg)
q->limit = limit;
q->kick = kick;
q->arg = arg;
+ q->state = Qmsg;
+
+ return q;
}
static int
@@ 288,12 304,12 @@ bfilled(void *a)
}
long
-qread(Queue *q, char *p, int len, int drop)
+qread(Queue *q, char *p, int len)
{
Block *b, *bb;
int x, n;
- /* ... to be replaced by a mapping */
+ /* ... to be replaced by a kmapping if need be */
b = allocb(len);
x = splhi();
@@ 311,24 327,31 @@ qread(Queue *q, char *p, int len, int drop)
sleep(&b->r, bfilled, b);
n = BLEN(b);
memmove(p, b->rp, n);
+ free(b);
return n;
}
- /* grab a block from the buffer */
- n = BLEN(b);
- if(drop || n <= len){
- q->bfirst = b->next;
- q->len -= n;
- unlock(q);
- slpx(x);
- memmove(p, b->rp, n);
- } else {
+ /* copy from a buffered block */
+ q->bfirst = bb->next;
+ n = BLEN(bb);
+ if(n > len)
n = len;
- q->len -= n;
- memmove(p, b->rp, n);
- b->rp += n;
+ q->len -= n;
+ unlock(q);
+ splx(x);
+ memmove(p, bb->rp, n);
+ bb->rp += n;
+
+ /* free it or put it back */
+ if(drop || bb->rp == bb->wp)
+ free(bb);
+ else {
+ x = splhi();
+ lock(q);
+ bb->next = q->bfirst;
+ q->bfirst = bb;
unlock(q);
- slpx(x);
+ splx(x);
}
free(b);
return n;
@@ 346,7 369,7 @@ long
qwrite(Queue *q, char *p, int len)
{
Block *b;
- int x, n;
+ int x;
b = allocb(len);
memmove(b->rp, p, len);
@@ 368,7 391,7 @@ qwrite(Queue *q, char *p, int len)
q->blast = b;
q->len += len;
if((q->state & Qstarve) && q->kick){
- q->stat &= ~Qstarve;
+ q->state &= ~Qstarve;
(*q->kick)(q->arg);
}
unlock(q);
M port/taslock.c => port/taslock.c +1 -2
@@ 19,9 19,8 @@ lock(Lock *l)
return;
}
}
- l->key = 0;
panic("lock loop 0x%lux key 0x%lux pc 0x%lux held by pc 0x%lux\n",
- l->key, i, pc, l->pc);
+ i, l->key, pc, l->pc);
}
int