--- /sys/src/9k/k10/dat.h +++ /sys/src/9k/k10/dat.h @@ -18,6 +18,7 @@ typedef u64int PTE; typedef struct Proc Proc; typedef struct Sys Sys; typedef u64int uintmem; /* horrible name */ +typedef vlong Tval; typedef struct Ureg Ureg; typedef struct Vctl Vctl; --- /sys/src/9k/port/alarm.c +++ /sys/src/9k/port/alarm.c @@ -16,7 +16,11 @@ alarmkproc(void*) for(;;){ now = sys->ticks; qlock(&alarms); - while((rp = alarms.head) && rp->alarm <= now){ + /* + * the odd test of now vs. rp->alarm is to cope with + * now wrapping around. + */ + while((rp = alarms.head) && (long)(now - rp->alarm) >= 0){ if(rp->alarm != 0L){ if(canqlock(&rp->debug)){ if(!waserror()){ @@ -48,7 +52,7 @@ checkalarms(void) p = alarms.head; now = sys->ticks; - if(p && p->alarm <= now) + if(p && (long)(now - p->alarm) >= 0) wakeup(&alarmr); } @@ -67,6 +71,8 @@ procalarm(ulong time) return old; } when = ms2tk(time)+sys->ticks; + if(when == 0) /* ticks have wrapped to 0? */ + when = 1; /* distinguish a wrapped alarm from no alarm */ qlock(&alarms); l = &alarms.head; @@ -82,7 +88,7 @@ procalarm(ulong time) if(alarms.head) { l = &alarms.head; for(f = *l; f; f = f->palarm) { - if(f->alarm > when) { + if((long)(f->alarm - when) >= 0) { up->palarm = f; *l = up; goto done; --- /sys/src/9k/port/allocb.c +++ /sys/src/9k/port/allocb.c @@ -8,6 +8,7 @@ enum { Hdrspc = 64, /* leave room for high-level headers */ Bdead = 0x51494F42, /* "QIOB" */ + Bmagic = 0x0910b10c, }; struct @@ -35,6 +36,7 @@ _allocb(int size) b->list = nil; b->free = 0; b->flag = 0; + b->magic = Bmagic; /* align base and bounds of data */ b->lim = (uchar*)(PTR2UINT(b) & ~(BLOCKALIGN-1)); @@ -59,10 +61,13 @@ allocb(int size) * Can still error out of here, though. */ if(up == nil) - panic("allocb without up: %#p\n", getcallerpc(&size)); + panic("allocb without up: %#p", getcallerpc(&size)); if((b = _allocb(size)) == nil){ + splhi(); mallocsummary(); - panic("allocb: no memory for %d bytes\n", size); + delay(500); + panic("allocb: no memory for %d bytes; caller %#p", size, + getcallerpc(&size)); } return b; @@ -120,6 +125,9 @@ freeb(Block *b) if(b == nil) return; + if(Bmagic && b->magic != Bmagic) + panic("freeb: bad magic %#lux in Block %#p; caller pc %#p", + b->magic, b, getcallerpc(&b)); /* * drivers which perform non cache coherent DMA manage their own buffer @@ -143,6 +151,7 @@ freeb(Block *b) b->wp = dead; b->lim = dead; b->base = dead; + b->magic = 0; free(p); } @@ -159,9 +168,10 @@ checkb(Block *b, char *msg) print("checkb: base %#p lim %#p next %#p\n", b->base, b->lim, b->next); print("checkb: rp %#p wp %#p\n", b->rp, b->wp); - panic("checkb dead: %s\n", msg); + panic("checkb dead: %s", msg); } - + if(Bmagic && b->magic != Bmagic) + panic("checkb: bad magic %#lux in Block %#p", b->magic, b); if(b->base > b->lim) panic("checkb 0 %s %#p %#p", msg, b->base, b->lim); if(b->rp < b->base) --- /sys/src/9k/port/aoe.h +++ /sys/src/9k/port/aoe.h @@ -73,6 +73,3 @@ typedef struct { } Aoeqc; #define AOEQCSZ offsetof(Aoeqc, payload[0]) - -extern char Echange[]; -extern char Enotup[]; --- /sys/src/9k/port/chan.c +++ /sys/src/9k/port/chan.c @@ -1166,7 +1166,7 @@ namelenerror(char *aname, int len, char *err) if(name <= aname) panic("bad math in namelenerror"); /* walk out of current UTF sequence */ - for(i=0; (*name&0xC0)==0x80 && i<3; i++) + for(i=0; (*name&0xC0)==0x80 && igenbuf, sizeof up->genbuf, "...%.*s", --- /sys/src/9k/port/devaoe.c +++ /sys/src/9k/port/devaoe.c @@ -160,6 +160,7 @@ typedef struct Srb Srb; struct Srb { Rendez; Srb *next; + int shared; /* Srb shared with kproc (don't free) */ ulong ticksent; ulong len; vlong sector; @@ -257,9 +258,6 @@ static int debug; static int autodiscover = 1; static int rediscover; -char Enotup[] = "aoe device is down"; -char Echange[] = "media or partition has changed"; - static Srb* srballoc(ulong sz) { @@ -270,6 +268,7 @@ srballoc(ulong sz) error(Enomem); srb->dp = srb->data = srb+1; srb->ticksent = sys->ticks; + srb->shared = 0; return srb; } @@ -283,17 +282,24 @@ srbkalloc(void *db, ulong) error(Enomem); srb->dp = srb->data = db; srb->ticksent = sys->ticks; + srb->shared = 0; return srb; } -#define srbfree(srb) free(srb) +static void +srbfree(Srb *srb) +{ + while(srb->shared) + sched(); + free(srb); +} static void srberror(Srb *srb, char *s) { srb->error = s; srb->nout--; - if (srb->nout == 0) + if(srb->nout == 0) wakeup(srb); } @@ -433,7 +439,7 @@ downdev(Aoedev *d, char *err) f = d->frames; e = f + d->nframes; for(; f < e; f->tag = Tfree, f->srb = nil, f++) - frameerror(d, f, Enotup); + frameerror(d, f, Eaoedown); d->inprocess = nil; eventlog("%æ: removed; %s\n", d, err); } @@ -945,7 +951,7 @@ aoeopen(Chan *c, int omode) nexterror(); } if(!UP(d)) - error(Enotup); + error(Eaoedown); c = devopen(c, omode, 0, 0, aoegen); d->nopen++; poperror(); @@ -1084,7 +1090,7 @@ srbready(void *v) Srb *s; s = v; - return s->error || (!s->nout && !s->len); + return s->error || (s->nout == 0 && s->len == 0); } static Frame* @@ -1140,6 +1146,7 @@ strategy(Aoedev *d, Srb *srb) d->tail = srb; if(d->head == nil) d->head = srb; + srb->shared = 1; work(d); poperror(); qunlock(d); @@ -1275,11 +1282,11 @@ unitread(Chan *c, void *db, long len, vlong off) return rw(d, Read, db, len, off); case Qconfig: if (!UP(d)) - error(Enotup); + error(Eaoedown); return readmem(off, db, len, d->config, d->nconfig); case Qident: if (!UP(d)) - error(Enotup); + error(Eaoedown); return readmem(off, db, len, d->ident, sizeof d->ident); } } @@ -1394,7 +1401,7 @@ configwrite(Aoedev *d, void *db, long len) Srb *srb; if(!UP(d)) - error(Enotup); + error(Eaoedown); if(len > ETHERMAXTU - AOEQCSZ) error(Etoobig); srb = srballoc(len); @@ -1402,6 +1409,7 @@ configwrite(Aoedev *d, void *db, long len) if(s == nil) error(Enomem); memmove(s, db, len); + if(waserror()){ srbfree(srb); free(s); @@ -1418,6 +1426,7 @@ configwrite(Aoedev *d, void *db, long len) break; poperror(); qunlock(d); + if(waserror()) nexterror(); tsleep(&up->sleep, return0, 0, 100); @@ -1426,8 +1435,16 @@ configwrite(Aoedev *d, void *db, long len) f->nhdr = AOEQCSZ; memset(f->hdr, 0, f->nhdr); ch = (Aoeqc*)f->hdr; - if(hset(d, f, ch, ACconfig) == -1) + if(hset(d, f, ch, ACconfig) == -1) { + /* + * these refer to qlock & waserror in the above for loop. + * there's still the first waserror outstanding. + */ + poperror(); + qunlock(d); return 0; + } + srb->shared = 1; f->srb = srb; f->dp = s; ch->verccmd = AQCfset; @@ -1436,10 +1453,7 @@ configwrite(Aoedev *d, void *db, long len) srb->nout++; f->dl->npkt++; f->dlen = len; - /* - * these refer to qlock & waserror in the above for loop. - * there's still the first waserror outstanding. - */ + /* these too */ poperror(); qunlock(d); @@ -1709,8 +1723,8 @@ newdev(long major, long minor, int n) d->flag = Djumbo; d->unit = newunit(); /* bzzt. inaccurate if units removed */ if(d->unit == -1){ - free(d); free(d->frames); + free(d); error("too many units"); } d->dl = d->dltab; @@ -1936,6 +1950,7 @@ qcfgrsp(Block *b, Netlink *nl) memmove(f->dp, ch + 1, cslen); f->srb->nout--; wakeup(f->srb); + f->srb->shared = 0; d->nout--; f->srb = nil; f->tag = Tfree; @@ -2159,8 +2174,10 @@ atarsp(Block *b) } } - if(srb && --srb->nout == 0 && srb->len == 0) + if(srb && --srb->nout == 0 && srb->len == 0){ wakeup(srb); + srb->shared = 0; + } f->srb = nil; f->tag = Tfree; d->nout--; @@ -2414,11 +2431,22 @@ removeaoedev(Aoedev *d) break; qlock(d); d->flag &= ~Dup; - newvers(d); + + /* + * Changing the version number is, strictly speaking, correct, + * but doing so means that deleting a LUN that is not in use + * invalidates all other LUNs too. If your file server has + * venti arenas or fossil file systems on 1.0, and you delete 1.1, + * since you no longer need it, 1.0 will become inaccessible to your + * file server, which will eventually panic. Note that newdev() + * does not change the version number. + */ + // newvers(d); + d->ndl = 0; qunlock(d); for(i = 0; i < d->nframes; i++) - frameerror(d, d->frames+i, Enotup); + frameerror(d, d->frames+i, Eaoedown); if(p) p->next = d->next; --- /sys/src/9k/port/devcap.c +++ /sys/src/9k/port/devcap.c @@ -112,7 +112,7 @@ hashstr(uchar *hash) int i; for(i = 0; i < Hashlen; i++) - sprint(buf+2*i, "%2.2ux", hash[i]); + seprint(buf+2*i, &buf[sizeof buf], "%2.2ux", hash[i]); buf[2*Hashlen] = 0; return buf; } --- /sys/src/9k/port/devcons.c +++ /sys/src/9k/port/devcons.c @@ -698,7 +698,7 @@ static Dirtab consdir[]={ "pid", {Qpid}, NUMSIZE, 0444, "ppid", {Qppid}, NUMSIZE, 0444, "random", {Qrandom}, 0, 0444, - "reboot", {Qreboot}, 0, 0664, + "reboot", {Qreboot}, 0, 0660, "swap", {Qswap}, 0, 0664, "sysname", {Qsysname}, 0, 0664, "sysstat", {Qsysstat}, 0, 0666, --- /sys/src/9k/port/devdup.c +++ /sys/src/9k/port/devdup.c @@ -29,10 +29,10 @@ dupgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) return 0; if(s & 1){ p = 0400; - sprint(up->genbuf, "%dctl", s/2); + snprint(up->genbuf, sizeof up->genbuf, "%dctl", s/2); }else{ p = perm[f->mode&3]; - sprint(up->genbuf, "%d", s/2); + snprint(up->genbuf, sizeof up->genbuf, "%d", s/2); } mkqid(&q, s+1, 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, p, dp); --- /sys/src/9k/port/devenv.c +++ /sys/src/9k/port/devenv.c @@ -146,6 +146,8 @@ envcreate(Chan *c, char *name, int omode, int) if(c->qid.type != QTDIR) error(Eperm); + if(strlen(name) >= sizeof up->genbuf) + error("name too long"); /* protect envgen */ omode = openmode(omode); eg = envgrp(c); --- /sys/src/9k/port/devmnt.c +++ /sys/src/9k/port/devmnt.c @@ -413,6 +413,7 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) alloc = 1; } wq->clone = nc; + nc->flag |= c->flag&CCACHE; if(waserror()) { mntfree(r); --- /sys/src/9k/port/devpipe.c +++ /sys/src/9k/port/devpipe.c @@ -12,6 +12,7 @@ struct Pipe Pipe *next; int ref; ulong path; + long perm; Queue *q[2]; int qref[2]; }; @@ -73,6 +74,7 @@ pipeattach(char *spec) lock(&pipealloc); p->path = ++pipealloc.path; unlock(&pipealloc); + p->perm = pipedir[Qdata0].perm; mkqid(&c->qid, PIPEQID(2*p->path, Qdir), 0, QTDIR); c->aux = p; @@ -109,7 +111,7 @@ pipegen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp) break; } mkqid(&q, PIPEQID(PIPEID(c->qid.path), tab->qid.path), 0, QTFILE); - devdir(c, q, tab->name, len, eve, tab->perm, dp); + devdir(c, q, tab->name, len, eve, p->perm, dp); return 1; } @@ -154,10 +156,10 @@ pipestat(Chan *c, uchar *db, long n) devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir); break; case Qdata0: - devdir(c, c->qid, "data", qlen(p->q[0]), eve, 0600, &dir); + devdir(c, c->qid, "data", qlen(p->q[0]), eve, p->perm, &dir); break; case Qdata1: - devdir(c, c->qid, "data1", qlen(p->q[1]), eve, 0600, &dir); + devdir(c, c->qid, "data1", qlen(p->q[1]), eve, p->perm, &dir); break; default: panic("pipestat"); @@ -168,6 +170,36 @@ pipestat(Chan *c, uchar *db, long n) return n; } +static long +pipewstat(Chan* c, uchar* db, long n) +{ + int m; + Dir *dir; + Pipe *p; + + p = c->aux; + if(strcmp(up->user, eve) != 0) + error(Eperm); + if(PIPETYPE(c->qid.path) == Qdir) + error(Eisdir); + + dir = smalloc(sizeof(Dir)+n); + if(waserror()){ + free(dir); + nexterror(); + } + m = convM2D(db, n, &dir[0], (char*)&dir[1]); + if(m == 0) + error(Eshortstat); + if(!emptystr(dir[0].uid)) + error("can't change owner"); + if(dir[0].mode != ~0UL) + p->perm = dir[0].mode; + poperror(); + free(dir); + return m; +} + /* * if the stream doesn't exist, create it */ @@ -380,5 +412,5 @@ Dev pipedevtab = { pipewrite, pipebwrite, devremove, - devwstat, + pipewstat, }; --- /sys/src/9k/port/devproc.c +++ /sys/src/9k/port/devproc.c @@ -133,16 +133,16 @@ static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", }; /* * Qids are, in path: - * 4 bits of file type (qids above) - * 23 bits of process slot number + 1 + * 5 bits of file type (qids above) + * 26 bits of process slot number + 1 * in vers, * 32 bits of pid, for consistency checking * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. */ #define QSHIFT 5 /* location in qid of proc slot # */ -#define QID(q) ((((ulong)(q).path)&0x0000001F)>>0) -#define SLOT(q) (((((ulong)(q).path)&0x07FFFFFE0)>>QSHIFT)-1) +#define QID(q) ((((ulong)(q).path) & ((1<> 0) +#define SLOT(q) (((((ulong)(q).path) & ~(1UL<<31)) >> QSHIFT) - 1) #define PID(q) ((q).vers) #define NOTEID(q) ((q).vers) @@ -213,7 +213,7 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp) if((p = psincref(s)) == nil || (pid = p->pid) == 0) return 0; - sprint(up->genbuf, "%d", pid); + snprint(up->genbuf, sizeof up->genbuf, "%d", pid); /* * String comparison is done in devwalk so * name must match its formatted pid. @@ -239,6 +239,7 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp) tab = &procdir[s]; path = c->qid.path&~(((1<procmode determines default mode for files in /proc */ if((p = psincref(SLOT(c->qid))) == nil) return -1; perm = tab->perm; @@ -289,7 +290,7 @@ _proctrace(Proc* p, Tevent etype, vlong ts) static void procinit(void) { - if(PROCMAX >= (1<<(16-QSHIFT))-1) + if(PROCMAX >= (1<<(31-QSHIFT))-1) print("warning: too many procs for devproc\n"); addclock0link((void (*)(void))profclock, 113); /* Relative prime to HZ */ } @@ -389,6 +390,7 @@ procopen(Chan *c, int omode) tc = proctext(c, p); tc->offset = 0; poperror(); + cclose(c); qunlock(&p->debug); psdecref(p); return tc; @@ -506,6 +508,7 @@ procwstat(Chan *c, uchar *db, long n) else kstrdup(&p->user, d->uid); } + /* p->procmode determines default mode for files in /proc */ if(d->mode != ~0UL) p->procmode = d->mode&0777; @@ -538,7 +541,7 @@ procqidwidth(Chan *c) { char buf[32]; - return sprint(buf, "%lud", c->qid.vers); + return snprint(buf, sizeof buf, "%lud", c->qid.vers); } int @@ -923,7 +926,8 @@ procread(Chan *c, void *va, long n, vlong off) sg = p->seg[i]; if(sg == 0) continue; - j += sprint(statbuf+j, "%-6s %c%c %p %p %4d\n", + j += snprint(statbuf+j, sizeof statbuf - j, + "%-6s %c%c %p %p %4d\n", sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ', sg->profile ? 'P' : ' ', @@ -989,6 +993,8 @@ procread(Chan *c, void *va, long n, vlong off) if(p->pgrp == nil || p->pid != PID(c->qid)) error(Eprocdied); mw = c->aux; + if(mw == nil) + error(Enomem); if(mw->cddone){ poperror(); qunlock(&p->debug); @@ -1249,8 +1255,10 @@ proctext(Chan *c, Proc *p) error(Eprocdied); } - if(p->pid != PID(c->qid)) + if(p->pid != PID(c->qid)){ + cclose(tc); error(Eprocdied); + } poperror(); unlock(i); --- /sys/src/9k/port/devsd.c +++ /sys/src/9k/port/devsd.c @@ -15,8 +15,6 @@ extern Dev sddevtab; extern SDifc* sdifc[]; -static char Echange[] = "media or partition has changed"; - static char devletters[] = "0123456789" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -485,7 +483,8 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) case Qtopdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); + snprint(up->genbuf, sizeof up->genbuf, "#%C", + sddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } @@ -533,7 +532,8 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp) case Qunitdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); + snprint(up->genbuf, sizeof up->genbuf, "#%C", + sddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } --- /sys/src/9k/port/devsrv.c +++ /sys/src/9k/port/devsrv.c @@ -86,13 +86,15 @@ srvstat(Chan *c, uchar *db, long n) char* srvname(Chan *c) { + int size; Srv *sp; char *s; for(sp = srv; sp; sp = sp->link) if(sp->chan == c){ - s = smalloc(3+strlen(sp->name)+1); - sprint(s, "#s/%s", sp->name); + size = 3+strlen(sp->name)+1; + s = smalloc(size); + snprint(s, size, "#s/%s", sp->name); return s; } return nil; --- /sys/src/9k/port/devssl.c +++ /sys/src/9k/port/devssl.c @@ -73,15 +73,15 @@ struct Dstate enum { Maxdmsg= 1<<16, - Maxdstate= 128, /* must be a power of 2 */ + Maxdstate= 512, /* max. open ssl conn's; must be a power of 2 */ }; -Lock dslock; -int dshiwat; -char *dsname[Maxdstate]; -Dstate *dstate[Maxdstate]; -char *encalgs; -char *hashalgs; +static Lock dslock; +static int dshiwat; +static char *dsname[Maxdstate]; +static Dstate *dstate[Maxdstate]; +static char *encalgs; +static char *hashalgs; enum{ Qtopdir = 1, /* top level directory */ @@ -168,7 +168,7 @@ sslgen(Chan *c, char*, Dirtab *d, int nd, int s, Dir *dp) else nm = eve; if(dsname[s] == nil){ - sprint(name, "%d", s); + snprint(name, sizeof name, "%d", s); kstrdup(&dsname[s], name); } devdir(c, q, dsname[s], 0, nm, 0555, dp); @@ -672,7 +672,7 @@ sslread(Chan *c, void *a, long n, vlong off) error(Ebadusefd); case Qctl: ft = CONV(c->qid); - sprint(buf, "%d", ft); + snprint(buf, sizeof buf, "%d", ft); return readstr(offset, a, n, buf); case Qdata: b = sslbread(c, n, offset); @@ -761,7 +761,7 @@ sslput(Dstate *s, Block * volatile b) if(waserror()){ if(b != nil) - free(b); + freeb(b); nexterror(); } @@ -894,6 +894,8 @@ initDESkey_40(OneWay *w) } w->state = malloc(sizeof(DESstate)); + if(w->state == nil) + error(Enomem); if(w->slen >= 16) setupDESstate(w->state, key, w->secret+8); else if(w->slen >= 8) @@ -930,6 +932,8 @@ initRC4key_40(OneWay *w) w->slen = 5; w->state = malloc(sizeof(RC4state)); + if(w->state == nil) + error(Enomem); setupRC4state(w->state, w->secret, w->slen); } @@ -949,6 +953,8 @@ initRC4key_128(OneWay *w) w->slen = 16; w->state = malloc(sizeof(RC4state)); + if(w->state == nil) + error(Enomem); setupRC4state(w->state, w->secret, w->slen); } @@ -1050,6 +1056,7 @@ sslwrite(Chan *c, void *a, long n, vlong) char *p, *np, *e, buf[128]; uchar *x; + x = nil; s = dstate[CONV(c->qid)]; if(s == 0) panic("sslwrite"); @@ -1125,6 +1132,10 @@ sslwrite(Chan *c, void *a, long n, vlong) if(p) *p++ = 0; + if(waserror()){ + free(x); + nexterror(); + } if(strcmp(buf, "fd") == 0){ s->c = buftochan(p); @@ -1144,9 +1155,8 @@ sslwrite(Chan *c, void *a, long n, vlong) s->state = Sclear; s->maxpad = s->max = (1<<15) - s->diglen - 1; - if(strcmp(p, "clear") == 0){ - goto out; - } + if(strcmp(p, "clear") == 0) + goto outx; if(s->in.secret && s->out.secret == 0) setsecret(&s->out, s->in.secret, s->in.slen); @@ -1187,17 +1197,21 @@ sslwrite(Chan *c, void *a, long n, vlong) l = (strlen(p)*3)/2; x = smalloc(l); t = dec64(x, l, p, strlen(p)); + if(t <= 0) + error(Ebadarg); setsecret(&s->in, x, t); - free(x); } else if(strcmp(buf, "secretout") == 0 && p != 0) { l = (strlen(p)*3)/2 + 1; x = smalloc(l); t = dec64(x, l, p, strlen(p)); + if(t <= 0) + error(Ebadarg); setsecret(&s->out, x, t); - free(x); } else error(Ebadarg); - +outx: + free(x); + poperror(); out: qunlock(&s->in.ctlq); qunlock(&s->out.q); --- /sys/src/9k/port/devtls.c +++ /sys/src/9k/port/devtls.c @@ -324,7 +324,7 @@ tlsgen(Chan *c, char*, Dirtab *, int, int s, Dir *dp) nm = eve; if((name = trnames[s]) == nil){ name = trnames[s] = smalloc(16); - sprint(name, "%d", s); + snprint(name, 16, "%d", s); } devdir(c, q, name, 0, nm, 0555, dp); unlock(&tdlock); --- /sys/src/9k/port/devuart.c +++ /sys/src/9k/port/devuart.c @@ -45,11 +45,13 @@ static void uartflow(void*); /* * enable/disable uart and add/remove to list of enabled uarts */ -static Uart* +Uart* uartenable(Uart *p) { Uart **l; + if(p->enabled) + return p; if(p->iq == nil){ if((p->iq = qopen(8*1024, 0, uartflow, p)) == nil) return nil; @@ -89,7 +91,11 @@ uartenable(Uart *p) uartctl(p, "b9600"); (*p->phys->enable)(p, 1); - lock(&uartalloc); + /* + * use ilock because uartclock can otherwise interrupt here + * and would hang on an attempt to lock uartalloc. + */ + ilock(&uartalloc); for(l = &uartalloc.elist; *l; l = &(*l)->elist){ if(*l == p) break; @@ -99,7 +105,7 @@ uartenable(Uart *p) uartalloc.elist = p; } p->enabled = 1; - unlock(&uartalloc); + iunlock(&uartalloc); return p; } @@ -109,9 +115,11 @@ uartdisable(Uart *p) { Uart **l; + if(!p->enabled) + return; (*p->phys->disable)(p); - lock(&uartalloc); + ilock(&uartalloc); for(l = &uartalloc.elist; *l; l = &(*l)->elist){ if(*l == p){ *l = p->elist; @@ -119,7 +127,7 @@ uartdisable(Uart *p) } } p->enabled = 0; - unlock(&uartalloc); + iunlock(&uartalloc); } Uart* @@ -212,15 +220,15 @@ uartreset(void) p = uartlist; for(i = 0; i < uartnuart; i++){ /* 3 directory entries per port */ - sprint(dp->name, "eia%d", i); + snprint(dp->name, sizeof dp->name, "eia%d", i); dp->qid.path = UARTQID(i, Qdata); dp->perm = 0660; dp++; - sprint(dp->name, "eia%dctl", i); + snprint(dp->name, sizeof dp->name, "eia%dctl", i); dp->qid.path = UARTQID(i, Qctl); dp->perm = 0660; dp++; - sprint(dp->name, "eia%dstatus", i); + snprint(dp->name, sizeof dp->name, "eia%dstatus", i); dp->qid.path = UARTQID(i, Qstat); dp->perm = 0444; dp++; @@ -524,6 +532,8 @@ uartwrite(Chan *c, void *buf, long n, vlong) break; case Qctl: cmd = malloc(n+1); + if(cmd == nil) + error(Enomem); memmove(cmd, buf, n); cmd[n] = 0; qlock(p); @@ -702,7 +712,7 @@ uartrecv(Uart *p, char ch) /* receive the character */ if(p->putc) p->putc(p->iq, ch); - else{ + else if (p->iw) { /* maybe the line isn't enabled yet */ ilock(&p->rlock); next = p->iw + 1; if(next == p->ie) @@ -776,8 +786,14 @@ uartgetc(void) void uartputc(int c) { - if(consuart == nil || consuart->phys->putc == nil) + char c2; + + if(consuart == nil || consuart->phys->putc == nil) { + c2 = c; + if (lprint) + (*lprint)(&c2, 1); return; + } consuart->phys->putc(consuart, c); } @@ -786,9 +802,11 @@ uartputs(char *s, int n) { char *e; - if(consuart == nil || consuart->phys->putc == nil) + if(consuart == nil || consuart->phys->putc == nil) { + if (lprint) + (*lprint)(s, n); return; - + } e = s+n; for(; sdisable(); } +static int +wdallowed(void) +{ + return getconf("*nowatchdog") == nil; +} + +static void +wdshutdown(void) +{ + if (wd) { + wd->disable(); + watchdogon = 0; + } +} + +/* called from clock interrupt, so restart needs ilock internally */ +static void +wdpet(void) +{ + /* watchdog could be paused; if so, don't restart */ + if (wdautopet && watchdogon) + wd->restart(); +} + +/* + * reassure the watchdog from the clock interrupt + * until the user takes control of it. + */ +static void +wdautostart(void) +{ + if (wdautopet || !wd || !wdallowed()) + return; + if (waserror()) { + print("watchdog: automatic enable failed\n"); + return; + } + wd->enable(); + poperror(); + + wdautopet = watchdogon = 1; + if (!wdclock0called) { + addclock0link(wdpet, 200); + wdclock0called = 1; + } +} + +/* + * disable strokes from the clock interrupt. + * have to disable the watchdog to mark it `not in use'. + */ +static void +wdautostop(void) +{ + if (!wdautopet) + return; + wdautopet = 0; + wdshutdown(); +} + +/* + * user processes exist and up is non-nil when the + * device init routines are called. + */ +static void +wdinit(void) +{ + wdautostart(); +} + static Chan* wdattach(char *spec) { @@ -51,12 +134,18 @@ wdstat(Chan *c, uchar *dp, long n) static Chan* wdopen(Chan* c, int omode) { - return devopen(c, omode, wddir, nelem(wddir), devgen); + wdautostop(); + c = devopen(c, omode, wddir, nelem(wddir), devgen); + if (c->qid.path == Qwdctl) + incref(&refs); + return c; } static void -wdclose(Chan*) +wdclose(Chan *c) { + if(c->qid.path == Qwdctl && c->flag&COPEN && decref(&refs) <= 0) + wdshutdown(); } static long @@ -126,8 +215,8 @@ Dev wddevtab = { "watchdog", devreset, - devinit, - devshutdown, + wdinit, + wdshutdown, wdattach, wdwalk, wdstat, --- /sys/src/9k/port/edf.c +++ /sys/src/9k/port/edf.c @@ -73,13 +73,14 @@ timeconv(Fmt *f) sign = ""; if (t > Onesecond){ t += OneRound; - sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), + snprint(buf, sizeof buf, "%s%d.%.3ds", sign, + (int)(t / Onesecond), (int)(t % Onesecond)/Onemillisecond); }else if (t > Onemillisecond) - sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), - (int)(t % Onemillisecond)); + snprint(buf, sizeof buf, "%s%d.%.3dms", sign, + (int)(t / Onemillisecond), (int)(t % Onemillisecond)); else - sprint(buf, "%s%dµs", sign, (int)t); + snprint(buf, sizeof buf, "%s%dµs", sign, (int)t); return fmtstrcpy(f, buf); } --- /sys/src/9k/port/error.h +++ /sys/src/9k/port/error.h @@ -39,7 +39,7 @@ extern char Eintr[]; /* interrupted */ extern char Enomem[]; /* kernel allocate failed */ extern char Esoverlap[]; /* segments overlap */ extern char Eshort[]; /* i/o count too small */ -extern char Egreg[]; /* ken has left the building */ +extern char Egreg[]; /* jmk added reentrancy for threads */ extern char Ebadspec[]; /* bad attach specifier */ extern char Enoreg[]; /* process has no saved registers */ extern char Enoattach[]; /* mount/attach disallowed */ @@ -47,3 +47,9 @@ extern char Eshortstat[]; /* stat buffer too small */ extern char Ebadstat[]; /* malformed stat buffer */ extern char Ecmdargs[]; /* wrong #args in control message */ extern char Ebadip[]; /* bad ip address syntax */ +extern char Edirseek[]; /* seek in directory */ +extern char Echange[]; /* media or partition has changed */ +extern char Estalled[]; /* endpoint stalled */ +extern char Edetach[]; /* device is detached */ +extern char Enotconf[]; /* endpoint not configured */ +extern char Eaoedown[]; /* aoe device is down */ --- /sys/src/9k/port/fault.c +++ /sys/src/9k/port/fault.c @@ -11,8 +11,10 @@ fault(uintptr addr, int read) Segment *s; char *sps; + if(up == nil) + panic("fault: nil up"); if(up->nlocks) - iprint("fault nlocks %d addr %#p\n", up->nlocks, addr); + print("fault: addr %#p: nlocks %d\n", addr, up->nlocks); sps = up->psstate; up->psstate = "Fault"; @@ -32,7 +34,7 @@ fault(uintptr addr, int read) return -1; } - if(fixfault(s, addr, read, 1) == 0) + if(fixfault(s, addr, read, 1) == 0) /* qunlocks s->lk */ break; /* @@ -61,6 +63,9 @@ faulterror(char *s, Chan *c, int freemem) pexit(s, freemem); } +void (*checkaddr)(ulong, Segment *, Page *); +ulong addr2check; + int fixfault(Segment *s, uintptr addr, int read, int dommuput) { @@ -170,6 +175,8 @@ fixfault(Segment *s, uintptr addr, int read, int dommuput) } } + if (checkaddr && addr == addr2check) + (*checkaddr)(addr, s, *pg); mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID; (*pg)->modref = PG_MOD|PG_REF; break; @@ -309,7 +316,7 @@ vmemchr(void *s, int c, int n) return t; a += r; n -= r; - if((a & KZERO) != KZERO) + if(a < KZERO) validaddr(UINT2PTR(a), 1, 0); } --- /sys/src/9k/port/netif.c +++ /sys/src/9k/port/netif.c @@ -98,7 +98,7 @@ netifgen(Chan *c, char*, Dirtab *vp, int, int i, Dir *dp) return 0; q.type = QTDIR; q.path = NETQID(i, N3rdqid); - sprint(up->genbuf, "%d", i); + snprint(up->genbuf, sizeof up->genbuf, "%d", i); devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp); break; } @@ -216,9 +216,11 @@ netifread(Netif *nif, Chan *c, void *a, long n, vlong off) return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE); case Nstatqid: p = malloc(READSTR); - j = snprint(p, READSTR, "in: %d\n", nif->inpackets); + if(p == nil) + error(Enomem); + j = snprint(p, READSTR, "in: %llud\n", nif->inpackets); j += snprint(p+j, READSTR-j, "link: %d\n", nif->link); - j += snprint(p+j, READSTR-j, "out: %d\n", nif->outpackets); + j += snprint(p+j, READSTR-j, "out: %llud\n", nif->outpackets); j += snprint(p+j, READSTR-j, "crc errs: %d\n", nif->crcs); j += snprint(p+j, READSTR-j, "overflows: %d\n", nif->overflows); j += snprint(p+j, READSTR-j, "soft overflows: %d\n", nif->soverflows); @@ -236,6 +238,8 @@ netifread(Netif *nif, Chan *c, void *a, long n, vlong off) return n; case Naddrqid: p = malloc(READSTR); + if(p == nil) + error(Enomem); j = 0; for(i = 0; i < nif->alen; i++) j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]); --- /sys/src/9k/port/page.c +++ /sys/src/9k/port/page.c @@ -244,7 +244,7 @@ newpage(int clear, Segment *s, uintptr va, int locked) lock(p); if(p->ref != 0) - panic("newpage"); + panic("newpage: p->ref %d != 0", p->ref); uncachepage(p); p->ref++; --- /sys/src/9k/port/pgrp.c +++ /sys/src/9k/port/pgrp.c @@ -5,6 +5,10 @@ #include "fns.h" #include "../port/error.h" +enum { + Whinesecs = 10, /* frequency of out-of-resources printing */ +}; + static Ref pgrpid; static Ref mountid; @@ -295,7 +299,9 @@ mountfree(Mount *mount) void resrcwait(char *reason) { + ulong now; char *p; + static ulong lastwhine; if(up == nil) panic("resrcwait"); @@ -303,7 +309,12 @@ resrcwait(char *reason) p = up->psstate; if(reason) { up->psstate = reason; - print("%s\n", reason); + now = seconds(); + /* don't tie up the console with complaints */ + if(now - lastwhine > Whinesecs) { + lastwhine = now; + print("%s\n", reason); + } } tsleep(&up->sleep, return0, 0, 300); --- /sys/src/9k/port/portclock.c +++ /sys/src/9k/port/portclock.c @@ -5,6 +5,11 @@ #include "fns.h" #include "ureg.h" +#include "../port/error.h" + +enum { + Maxtimerloops = 20*1000, +}; struct Timers { @@ -13,6 +18,7 @@ struct Timers }; static Timers timers[MACHMAX]; +static int timersinited; ulong intrcount[MACHMAX]; ulong fcallcount[MACHMAX]; @@ -181,19 +187,22 @@ hzclock(Ureg *ur) } void -timerintr(Ureg *u, vlong) +timerintr(Ureg *u, Tval) { Timer *t; Timers *tt; vlong when, now; - int callhzclock; + int count, callhzclock; intrcount[m->machno]++; callhzclock = 0; tt = &timers[m->machno]; now = fastticks(nil); + if(now == 0) + panic("timerintr: zero fastticks()"); ilock(tt); - while(t = tt->head){ + count = Maxtimerloops; + while((t = tt->head) != nil){ /* * No need to ilock t here: any manipulation of t * requires tdel(t) and this must be done with a @@ -220,6 +229,12 @@ timerintr(Ureg *u, vlong) ilock(tt); if(t->tmode == Tperiodic) tadd(tt, t); + if (--count <= 0) { + count = Maxtimerloops; + iprint("timerintr: probably stuck in while loop; " + "scrutinise clock.c or use faster cycle " + "counter\n"); + } } iunlock(tt); } @@ -232,8 +247,11 @@ timersinit(void) /* * T->tf == nil means the HZ clock for this processor. */ + timersinited = 1; todinit(); t = malloc(sizeof(*t)); + if(t == nil) + error(Enomem); t->tmode = Tperiodic; t->tt = nil; t->tns = 1000000000/HZ; @@ -247,8 +265,12 @@ addclock0link(void (*f)(void), int ms) Timer *nt; vlong when; + if(!timersinited) + panic("addclock0link: timersinit not called yet"); /* Synchronize to hztimer if ms is 0 */ nt = malloc(sizeof(Timer)); + if(nt == nil) + error(Enomem); if(ms == 0) ms = 1000/HZ; nt->tns = (vlong)ms*1000000LL; --- /sys/src/9k/port/portdat.h +++ /sys/src/9k/port/portdat.h @@ -10,6 +10,7 @@ typedef struct Dirtab Dirtab; typedef struct Edf Edf; typedef struct Egrp Egrp; typedef struct Evalue Evalue; +typedef struct Execvals Execvals; typedef struct Fastcall Fastcall; typedef struct Fgrp Fgrp; typedef struct Image Image; @@ -78,6 +79,7 @@ struct QLock Proc *head; /* next process waiting for object */ Proc *tail; /* last process waiting for object */ int locked; /* flag */ + uintptr qpc; /* pc of the holder */ }; struct RWlock @@ -141,6 +143,7 @@ struct Block void (*free)(Block*); ushort flag; ushort checksum; /* IP checksum of complete packet (minus media header) */ + ulong magic; }; #define BLEN(s) ((s)->wp - (s)->rp) #define BALLOC(s) ((s)->lim - (s)->base) @@ -516,7 +519,8 @@ struct Timer /* Internal */ Lock; Timers *tt; /* Timers queue this timer runs on */ - vlong twhen; /* ns represented in fastticks */ + Tval tticks; /* tns converted to ticks */ + Tval twhen; /* ns represented in fastticks */ Timer *tnext; }; @@ -763,6 +767,12 @@ enum READSTR = 4000, /* temporary buffer size for device reads */ }; +struct Execvals { + uvlong entry; + ulong textsize; + ulong datasize; +}; + extern char* conffile; extern char configfile[]; extern int cpuserver; @@ -774,6 +784,7 @@ extern Ref noteidalloc; extern int nphysseg; extern int nsyscall; extern Palloc palloc; + int (*parseboothdr)(Chan *, ulong, Execvals *); extern Physseg physseg[]; extern Procalloc procalloc; extern uint qiomaxatomic; @@ -925,6 +936,8 @@ struct Uart extern Uart* consuart; +void (*lprint)(char *, int); + /* * performance timers, all units in perfticks */ --- /sys/src/9k/port/portfns.h +++ /sys/src/9k/port/portfns.h @@ -150,6 +150,7 @@ void (*kproftimer)(uintptr); void ksetenv(char*, char*, int); void kstrcpy(char*, char*, int); void kstrdup(char**, char*); +ulong l2be(long); long latin1(Rune*, int); int lock(Lock*); void logopen(Log*); --- /sys/src/9k/port/proc.c +++ /sys/src/9k/port/proc.c @@ -1353,13 +1353,6 @@ kproc(char *name, void (*func)(void *), void *arg) memset(p->time, 0, sizeof(p->time)); p->time[TReal] = sys->ticks; ready(p); - /* - * since the bss/data segments are now shareable, - * any mmu info about this process is now stale - * and has to be discarded. - */ - p->newtlb = 1; - mmuflush(); } /* @@ -1429,7 +1422,7 @@ exhausted(char *resource) { char buf[ERRMAX]; - sprint(buf, "no free %s", resource); + snprint(buf, sizeof buf, "no free %s", resource); iprint("%s\n", buf); error(buf); } --- /sys/src/9k/port/qlock.c +++ /sys/src/9k/port/qlock.c @@ -27,6 +27,7 @@ qlock(QLock *q) rwstats.qlock++; if(!q->locked) { q->locked = 1; + q->qpc = getcallerpc(&q); unlock(&q->use); return; } @@ -44,6 +45,7 @@ qlock(QLock *q) up->qpc = getcallerpc(&q); unlock(&q->use); sched(); + q->qpc = getcallerpc(&q); } int @@ -56,6 +58,7 @@ canqlock(QLock *q) return 0; } q->locked = 1; + q->qpc = getcallerpc(&q); unlock(&q->use); return 1; @@ -80,6 +83,7 @@ qunlock(QLock *q) return; } q->locked = 0; + q->qpc = 0; unlock(&q->use); } --- /sys/src/9k/port/rebootcmd.c +++ /sys/src/9k/port/rebootcmd.c @@ -6,18 +6,23 @@ #include "../port/error.h" #include +#include "/sys/src/libmach/elf.h" -static ulong -l2be(long l) -{ - uchar *cp; +enum { + Ehdr32sz = 52, + Phdr32sz = 32, + Shdr32sz = 40, - cp = (uchar*)&l; - return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; -} + Ehdr64sz = 64, + Phdr64sz = 56, + Shdr64sz = 64, +}; +static uchar elfident[] = { + '\177', 'E', 'L', 'F', +}; -static void +void readn(Chan *c, void *vp, long n) { char *p; @@ -34,6 +39,49 @@ readn(Chan *c, void *vp, long n) } } +/* assume the elf header is in the byte order of this machine */ +int +readelfhdr(Chan *c, ulong, Execvals *evp) +{ + Ehdr ehdr; + Phdr phdrs[3]; + + c->offset = 0; /* back up */ + readn(c, &ehdr, sizeof ehdr); + if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 || + ehdr.ident[CLASS] != ELFCLASS32) + return -1; + + /* get textsize and datasize from Phdrs */ + readn(c, phdrs, sizeof phdrs); + evp->entry = ehdr.elfentry; + evp->textsize = phdrs[0].filesz; + evp->datasize = phdrs[1].filesz; + c->offset = ROUNDUP(Ehdr32sz + 3*Phdr32sz, 16); /* position for text */ + return 0; +} + +static int +readelf64hdr(Chan *c, ulong, Execvals *evp) +{ + E64hdr ehdr; + P64hdr phdrs[3]; + + c->offset = 0; /* back up */ + readn(c, &ehdr, sizeof ehdr); + if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 || + ehdr.ident[CLASS] != ELFCLASS64) + return -1; + + /* get textsize and datasize from Phdrs */ + readn(c, phdrs, sizeof phdrs); + evp->entry = ehdr.elfentry; + evp->textsize = phdrs[0].filesz; + evp->datasize = phdrs[1].filesz; + c->offset = ROUNDUP(Ehdr64sz + 3*Phdr64sz, 16); /* position for text */ + return 0; +} + static void setbootcmd(int argc, char *argv[]) { @@ -57,6 +105,7 @@ rebootcmd(int argc, char *argv[]) { Chan *c; Exec exec; + Execvals ev; ulong magic, text, rtext, entry, data, size; uchar *p; @@ -71,11 +120,25 @@ rebootcmd(int argc, char *argv[]) readn(c, &exec, sizeof(Exec)); magic = l2be(exec.magic); - entry = l2be(exec.entry); - text = l2be(exec.text); - data = l2be(exec.data); - if(magic != AOUT_MAGIC) + /* + * AOUT_MAGIC is sometimes defined like this: + * #define AOUT_MAGIC V_MAGIC || magic==M_MAGIC + * so we can only use it in a fairly stylized manner. + */ + if(magic == AOUT_MAGIC) { + entry = l2be(exec.entry); + text = l2be(exec.text); + data = l2be(exec.data); + } else if(parseboothdr && (*parseboothdr)(c, magic, &ev) >= 0 || + readelfhdr(c, magic, &ev) >= 0 || + readelf64hdr(c, magic, &ev) >= 0){ + entry = ev.entry; + text = ev.textsize; + data = ev.datasize; + } else { error(Ebadexec); + return; /* for the compiler */ + } /* round text out to page boundary */ rtext = ROUNDUP(entry+text, PGSZ)-entry; --- /sys/src/9k/port/sdaoe.c +++ /sys/src/9k/port/sdaoe.c @@ -15,9 +15,6 @@ #include "etherif.h" #include "../port/aoe.h" -extern char Echange[]; -extern char Enotup[]; - #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__); enum { @@ -502,7 +499,7 @@ aoerio(SDreq *r) if(waserror()){ if(strcmp(up->errstr, Echange) == 0 || - strcmp(up->errstr, Enotup) == 0) + strcmp(up->errstr, Eaoedown) == 0) unit->sectors = 0; nexterror(); } --- /sys/src/9k/port/syscallfmt.c +++ /sys/src/9k/port/syscallfmt.c @@ -230,6 +230,11 @@ syscallfmt(int syscallno, va_list list) i[0] = va_arg(list, int); fmtprint(&fmt, "%#p %d", v, i[0]); break; + case TSEMACQUIRE: + v = va_arg(list, long*); + l = va_arg(list, ulong); + fmtprint(&fmt, "%#p %ld", v, l); + break; case SEEK: v = va_arg(list, vlong*); i[0] = va_arg(list, int); @@ -321,14 +330,14 @@ sysretfmt(int syscallno, va_list list, Ar0* ar0, uvlong start, uvlong stop) switch(syscallno){ default: if(ar0->i == -1) - errstr = up->errstr; + errstr = up->syserrstr; fmtprint(&fmt, " = %d", (int)ar0->i); break; case ALARM: case _WRITE: case PWRITE: if(ar0->l == -1) - errstr = up->errstr; + errstr = up->syserrstr; fmtprint(&fmt, " = %ld", (long)ar0->l); break; case NSEC: @@ -339,7 +348,7 @@ sysretfmt(int syscallno, va_list list, Ar0* ar0, uvlong start, uvlong stop) case SEGATTACH: case RENDEZVOUS: if(ar0->v == (void*)-1) - errstr = up->errstr; + errstr = up->syserrstr; fmtprint(&fmt, " = %#p", ar0->v); break; case AWAIT: @@ -351,7 +360,7 @@ sysretfmt(int syscallno, va_list list, Ar0* ar0, uvlong start, uvlong stop) } else{ fmtprint(&fmt, "%#p/\"\" %lud = %d", a, l, (int)ar0->i); - errstr = up->errstr; + errstr = up->syserrstr; } break; case _ERRSTR: @@ -367,7 +376,7 @@ sysretfmt(int syscallno, va_list list, Ar0* ar0, uvlong start, uvlong stop) } else{ fmtprint(&fmt, "\"\" %lud = %d", l, (int)ar0->i); - errstr = up->errstr; + errstr = up->syserrstr; } break; case FD2PATH: @@ -381,7 +390,7 @@ sysretfmt(int syscallno, va_list list, Ar0* ar0, uvlong start, uvlong stop) } else{ fmtprint(&fmt, "\"\" %lud = %d", l, (int)ar0->i); - errstr = up->errstr; + errstr = up->syserrstr; } break; case _READ: @@ -396,7 +405,7 @@ sysretfmt(int syscallno, va_list list, Ar0* ar0, uvlong start, uvlong stop) } else{ fmtprint(&fmt, "/\"\""); - errstr = up->errstr; + errstr = up->syserrstr; } fmtprint(&fmt, " %ld", l); if(syscallno == PREAD){ --- /sys/src/9k/port/sysproc.c +++ /sys/src/9k/port/sysproc.c @@ -215,7 +215,7 @@ vl2be(uvlong v) |((uvlong)(p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]); } -static ulong +ulong l2be(long l) { uchar *cp; --- /sys/src/9k/port/tod.c +++ /sys/src/9k/port/tod.c @@ -58,10 +58,10 @@ todinit(void) if(tod.init) return; ilock(&tod); + tod.init = 1; /* prevent reentry via fastticks */ tod.last = fastticks((uvlong *)&tod.hz); iunlock(&tod); todsetfreq(tod.hz); - tod.init = 1; addclock0link(todfix, 100); } @@ -71,6 +71,8 @@ todinit(void) void todsetfreq(vlong f) { + if (f <= 0) + panic("todsetfreq: freq %lld <= 0", f); ilock(&tod); tod.hz = f; @@ -106,7 +108,11 @@ todset(vlong t, vlong delta, int n) n = -delta; if(delta > 0 && n > delta) n = delta; - delta = delta/n; + if (n == 0) { + iprint("todset: n == 0, delta == %lld\n", delta); + delta = 0; + } else + delta /= n; tod.sstart = sys->ticks; tod.send = tod.sstart + n; tod.delta = delta; @@ -198,7 +204,7 @@ todfix(void) /* convert to epoch */ mul64fract(&x, diff, tod.multiplier); -if(x > 30000000000ULL) print("todfix %llud\n", x); +if(x > 30000000000ULL) iprint("todfix %llud\n", x); x += tod.off; /* protect against overflows */ @@ -212,13 +218,7 @@ if(x > 30000000000ULL) print("todfix %llud\n", x); long seconds(void) { - vlong x; - int i; - - x = todget(nil); - x = x/TODFREQ; - i = x; - return i; + return (vlong)todget(nil) / TODFREQ; } uvlong