Kernel changes: - add background ccloses to make all processes killable - move away from vlongs in timer for performance - new event ctl message. [rsc] --rw-rw-r-- M 1428987 glenda sys 12062 Jan 28 09:29 sys/man/3/proc /n/sourcesdump/2006/0128/plan9/sys/man/3/proc:351,357 - /n/sourcesdump/2006/0129/plan9/sys/man/3/proc:351,363 perform a schedulability test and start scheduling the process as a real-time process if the test succeeds. If the test fails, the .B write - will fail with error set to the reason for failure. For details on real time, read on. + will fail with error set to the reason for failure. + .TP 10n + .B event + Add a user event to the + .B /proc/trace + file. + .PD .PP Real-time processes are periodically .IR released , [rsc] --rw-rw-r-- M 1428987 glenda sys 34790 Jan 28 09:24 sys/src/9/port/chan.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/chan.c:487,492 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/chan.c:487,568 } /* + * Queue a chan to be closed by one of the clunk procs. + */ + struct { + Chan *head; + Chan *tail; + int nqueued; + int nclosed; + Lock l; + QLock q; + Rendez r; + } clunkq; + void closeproc(void*); + + void + ccloseq(Chan *c) + { + if(c->flag&CFREE) + panic("cclose %lux", getcallerpc(&c)); + + DBG("ccloseq %p name=%s ref=%ld\n", c, c->path->s, c->ref); + + if(decref(c)) + return; + + lock(&clunkq.l); + clunkq.nqueued++; + c->next = nil; + if(clunkq.head) + clunkq.tail->next = c; + else + clunkq.head = c; + clunkq.tail = c; + unlock(&clunkq.l); + + if(!wakeup(&clunkq.r)) + kproc("closeproc", closeproc, nil); + } + + static int + clunkwork(void*) + { + return clunkq.head != nil; + } + + void + closeproc(void*) + { + Chan *c; + + for(;;){ + qlock(&clunkq.q); + if(clunkq.head == nil){ + if(!waserror()){ + tsleep(&clunkq.r, clunkwork, nil, 5000); + poperror(); + } + if(clunkq.head == nil){ + qunlock(&clunkq.q); + pexit("no work", 1); + } + } + lock(&clunkq.l); + c = clunkq.head; + clunkq.head = c->next; + clunkq.nclosed++; + unlock(&clunkq.l); + qunlock(&clunkq.q); + if(!waserror()){ + devtab[c->type]->close(c); + poperror(); + } + chanfree(c); + } + } + + /* * Make sure we have the only copy of c. (Copy on write.) */ Chan* /n/sourcesdump/2006/0128/plan9/sys/src/9/port/chan.c:1691,1693 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/chan.c:1767,1770 free(m); } } + [rsc] --rw-rw-r-- M 1428987 glenda sys 14579 Jan 28 09:26 sys/src/9/port/devloopback.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devloopback.c:143,149 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devloopback.c:143,149 lb->ref++; if(lb->ref == 1){ for(chan = 0; chan < 2; chan++){ - lb->link[chan].ci.mode = Tabsolute; + lb->link[chan].ci.mode = Trelative; lb->link[chan].ci.a = &lb->link[chan]; lb->link[chan].ci.f = linkintr; lb->link[chan].limit = Loopqlim; /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devloopback.c:685,691 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devloopback.c:685,691 if(!tin || tin > tout && tout) tin = tout; - link->ci.ns = tin; + link->ci.ns = tin - now; if(tin){ if(tin < now) panic("loopback unfinished business"); [rsc] --rw-rw-r-- M 1428987 glenda sys 30866 Jan 28 09:23 sys/src/9/port/devsd.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devsd.c:636,641 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devsd.c:636,642 sdev = sdgetdev(DEV(c->qid)); if(sdev == nil) error(Enonexist); + unit = sdev->unit[UNIT(c->qid)]; switch(TYPE(c->qid)){ /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devsd.c:646,651 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devsd.c:647,653 c->qid.vers = unit->vers; if(tas(&unit->rawinuse) != 0){ c->flag &= ~COPEN; + decref(&sdev->r); error(Einuse); } unit->state = Rawcmd; /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devsd.c:655,660 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devsd.c:657,663 if(waserror()){ qunlock(&unit->ctl); c->flag &= ~COPEN; + decref(&sdev->r); nexterror(); } pp = &unit->part[PART(c->qid)]; /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devsd.c:704,711 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devsd.c:707,716 ulong bno, max, nb, offset; sdev = sdgetdev(DEV(c->qid)); - if(sdev == nil) + if(sdev == nil){ + decref(&sdev->r); error(Enonexist); + } unit = sdev->unit[UNIT(c->qid)]; if(unit == nil) error(Enonexist); /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devsd.c:1101,1107 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devsd.c:1106,1112 if(unit->sectors){ if(unit->dev->ifc->rctl == nil) l += snprint(p+l, m-l, - "geometry %ld %ld\n", + "geometry %lud %ld\n", unit->sectors, unit->secsize); pp = unit->part; for(i = 0; i < unit->npart; i++){ [jmk] --rw-rw-r-- M 1428987 glenda sys 13489 Jan 28 13:22 sys/src/9/port/edf.c [diffs elided - too long] [diff -c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/edf.c /n/sourcesdump/2006/0129/plan9/sys/src/9/port/edf.c] [rsc] --rw-rw-r-- M 1428987 glenda sys 4760 Jan 28 09:24 sys/src/9/port/pgrp.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/pgrp.c:211,223 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/pgrp.c:211,262 if(decref(f) != 0) return; + /* + * If we get into trouble, forceclosefgrp + * will bail us out. + */ + up->closingfgrp = f; for(i = 0; i <= f->maxfd; i++) - if(c = f->fd[i]) + if(c = f->fd[i]){ + f->fd[i] = nil; cclose(c); + } + up->closingfgrp = nil; free(f->fd); free(f); } + + /* + * Called from sleep because up is in the middle + * of closefgrp and just got a kill ctl message. + * This usually means that up has wedged because + * of some kind of deadly embrace with mntclose + * trying to talk to itself. To break free, hand the + * unclosed channels to the close queue. Once they + * are finished, the blocked cclose that we've + * interrupted will finish by itself. + */ + void + forceclosefgrp(void) + { + int i; + Chan *c; + Fgrp *f; + + if(up->procctl != Proc_exitme || up->closingfgrp == nil){ + print("bad forceclosefgrp call"); + return; + } + + f = up->closingfgrp; + for(i = 0; i <= f->maxfd; i++) + if(c = f->fd[i]){ + f->fd[i] = nil; + ccloseq(c); + } + } + Mount* newmount(Mhead *mh, Chan *to, int flag, char *spec) [rsc] --rw-rw-r-- M 1428987 glenda sys 4211 Jan 28 09:26 sys/src/9/port/portclock.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portclock.c:17,23 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portclock.c:17,23 ulong intrcount[MAXMACH]; ulong fcallcount[MAXMACH]; - static uvlong + static vlong tadd(Timers *tt, Timer *nt) { Timer *t, **last; /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portclock.c:29,40 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portclock.c:29,38 panic("timer"); break; case Trelative: - assert(nt->tns > 0); + if(nt->tns <= 0) + nt->tns = 1; nt->twhen = fastticks(nil) + ns2fastticks(nt->tns); break; - case Tabsolute: - nt->twhen = tod2fastticks(nt->tns); - break; case Tperiodic: assert(nt->tns >= 100000); /* At least 100 µs period */ if(nt->twhen == 0){ /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portclock.c:94,108 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portclock.c:92,97 Timers *tt; vlong when; - if (nt->tmode == Tabsolute){ - when = todget(nil); - if (nt->tns <= when){ - // if (nt->tns + MS2NS(10) <= when) /* small deviations will happen */ - // print("timeradd (%lld %lld) %lld too early 0x%lux\n", - // when, nt->tns, when - nt->tns, getcallerpc(&nt)); - nt->tns = when; - } - } /* Must lock Timer struct before Timers struct */ ilock(nt); if(tt = nt->tt){ [rsc] --rw-rw-r-- M 1428987 glenda sys 22535 Jan 28 09:26 sys/src/9/port/portdat.h /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portdat.h:506,512 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portdat.h:506,511 enum { /* Mode */ Trelative, /* timer programmed in ns from now */ - Tabsolute, /* timer programmed in ns since epoch */ Tperiodic, /* periodic timer, period in ns */ }; /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portdat.h:630,635 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portdat.h:629,636 Egrp *egrp; /* Environment group */ Fgrp *fgrp; /* File descriptor group */ Rgrp *rgrp; /* Rendez group */ + + Fgrp *closingfgrp; /* used during teardown */ ulong parentpid; ulong time[6]; /* User, Sys, Real; child U, S, R */ [rsc] --rw-rw-r-- M 1428987 glenda sys 6279 Jan 28 09:54 sys/src/9/pc/i8253.c [rsc] --rw-rw-r-- M 1428987 glenda sys 5704 Jan 28 09:52 sys/src/9/port/alloc.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/alloc.c:95,100 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/alloc.c:95,101 pv = p->private; ilock(&pv->lk); + pv->lk.pc = getcallerpc(&p); pv->msg[0] = 0; } [rsc] --rw-rw-r-- M 1428987 glenda sys 7265 Jan 28 09:50 sys/src/9/port/fault.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/fault.c:11,17 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/fault.c:11,17 Segment *s; char *sps; - if(up && up->nlocks.ref) print("fault nlocks %ld\n", up->nlocks.ref); + if(up->nlocks.ref) print("fault nlocks %ld\n", up->nlocks.ref); sps = up->psstate; up->psstate = "Fault"; [rsc] --rw-rw-r-- M 1428987 glenda sys 5336 Jan 28 09:45 sys/src/9/port/tod.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/tod.c:31,43 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/tod.c:31,46 /* frequency of the tod clock */ #define TODFREQ 1000000000ULL + #define MicroFREQ 1000000ULL struct { int init; // true if initialized ulong cnt; Lock; - uvlong multiplier; // t = off + (multiplier*ticks)>>31 - uvlong divider; // ticks = (divider*(ticks-off))>>31 + uvlong multiplier; // ns = off + (multiplier*ticks)>>31 + uvlong divider; // ticks = (divider*(ns-off))>>31 + uvlong umultiplier; // µs = (µmultiplier*ticks)>>31 + uvlong udivider; // ticks = (µdivider*µs)>>31 vlong hz; // frequency of fast clock vlong last; // last reading of fast clock vlong off; // offset from epoch to last /n/sourcesdump/2006/0128/plan9/sys/src/9/port/tod.c:72,78 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/tod.c:75,82 /* calculate multiplier for time conversion */ tod.multiplier = mk64fract(TODFREQ, f); tod.divider = mk64fract(f, TODFREQ); - + tod.umultiplier = mk64fract(MicroFREQ, f); + tod.udivider = mk64fract(f, MicroFREQ); iunlock(&tod); } /n/sourcesdump/2006/0128/plan9/sys/src/9/port/tod.c:211,216 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/tod.c:215,242 x = x/TODFREQ; i = x; return i; + } + + uvlong + fastticks2us(uvlong ticks) + { + uvlong res; + + if(!tod.init) + todinit(); + mul64fract(&res, ticks, tod.umultiplier); + return res; + } + + uvlong + us2fastticks(uvlong us) + { + uvlong res; + + if(!tod.init) + todinit(); + mul64fract(&res, us, tod.udivider); + return res; } // convert milliseconds to fast ticks [rsc] --rw-rw-r-- M 1428987 glenda sys 11079 Jan 28 12:32 sys/src/9/port/portfns.h /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portfns.h:31,36 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portfns.h:31,37 void cinit(void); Chan* cclone(Chan*); void cclose(Chan*); + void ccloseq(Chan*); void closeegrp(Egrp*); void closefgrp(Fgrp*); void closepgrp(Pgrp*); /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portfns.h:102,107 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portfns.h:103,109 void exit(int); uvlong fastticks(uvlong*); uvlong fastticks2ns(uvlong); + uvlong fastticks2us(uvlong); int fault(ulong, int); void fdclose(int, int); Chan* fdtochan(int, int, int, int); /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portfns.h:108,113 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portfns.h:110,116 int findmount(Chan**, Mhead**, int, int, Qid); int fixfault(Segment*, ulong, int, int); void flushmmu(void); + void forceclosefgrp(void); void forkchild(Proc*, Ureg*); void forkret(void); void free(void*); /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portfns.h:336,342 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portfns.h:339,344 void todinit(void); void todset(vlong, vlong, int); Block* trimblock(Block*, int, int); - void tnsleep(Rendez*, int (*)(void*), void*, vlong); void tsleep(Rendez*, int (*)(void*), void*, ulong); int uartctl(Uart*, char*); int uartgetc(void); /n/sourcesdump/2006/0128/plan9/sys/src/9/port/portfns.h:351,356 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/portfns.h:353,359 void uncachepage(Page*); long unionread(Chan*, void*, long); void unlock(Lock*); + uvlong us2fastticks(uvlong); void userinit(void); ulong userpc(void); long userwrite(char*, int); [rsc] --rw-rw-r-- M 1428987 glenda sys 28497 Jan 28 12:29 sys/src/9/port/devproc.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:62,67 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:62,68 CMadmit, CMextra, CMexpel, + CMevent, }; enum{ /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:125,130 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:126,132 CMadmit, "admit", 1, CMextra, "extra", 1, CMexpel, "expel", 1, + CMevent, "event", 1, }; /* Segment type from portdat.h */ /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:1289,1294 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:1291,1297 Cmdtab *ct; vlong time; char *e; + void (*pt)(Proc*, int, vlong); if(p->kp) /* no ctl requests to kprocs */ error(Eperm); /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:1317,1329 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:1320,1332 unbreak(p); break; case Stopped: - postnote(p, 0, "sys: killed", NExit); p->procctl = Proc_exitme; + postnote(p, 0, "sys: killed", NExit); ready(p); break; default: - postnote(p, 0, "sys: killed", NExit); p->procctl = Proc_exitme; + postnote(p, 0, "sys: killed", NExit); } break; case CMnohang: /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:1402,1411 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:1405,1414 case CMperiod: if(p->edf == nil) edfinit(p); - if(e=parsetime(&time, cb->f[1])) + if(e=parsetime(&time, cb->f[1])) /* time in ns */ error(e); edfstop(p); - p->edf->T = time; + p->edf->T = time/1000; /* Edf times are in µs */ break; case CMdeadline: if(p->edf == nil) /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:1413,1419 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:1416,1422 if(e=parsetime(&time, cb->f[1])) error(e); edfstop(p); - p->edf->D = time; + p->edf->D = time/1000; break; case CMcost: if(p->edf == nil) /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:1421,1427 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:1424,1430 if(e=parsetime(&time, cb->f[1])) error(e); edfstop(p); - p->edf->C = time; + p->edf->C = time/1000; break; case CMsporadic: if(p->edf == nil) /n/sourcesdump/2006/0128/plan9/sys/src/9/port/devproc.c:1447,1452 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/devproc.c:1450,1460 case CMexpel: if(p->edf) edfstop(p); + break; + case CMevent: + pt = proctrace; + if(up->trace && pt) + pt(up, SUser, 0); break; } [rsc] --rw-rw-r-- M 1428987 sape sys 1195 Jan 28 12:24 sys/src/9/port/edf.h /n/sourcesdump/2006/0128/plan9/sys/src/9/port/edf.h:16,44 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/edf.h:16,45 typedef struct Edf Edf; struct Edf { + /* All times in µs */ /* time intervals */ - vlong D; /* Deadline */ - vlong Delta; /* Inherited deadline */ - vlong T; /* period */ - vlong C; /* Cost */ - vlong S; /* Slice: time remaining in this period */ - /* times */ - vlong r; /* (this) release time */ - vlong d; /* (this) deadline */ - vlong t; /* Start of next period, t += T at release */ - vlong s; /* Time at which this proc was last scheduled */ + long D; /* Deadline */ + long Delta; /* Inherited deadline */ + long T; /* period */ + long C; /* Cost */ + long S; /* Slice: time remaining in this period */ + /* times (only low-order bits of absolute time) */ + long r; /* (this) release time */ + long d; /* (this) deadline */ + long t; /* Start of next period, t += T at release */ + long s; /* Time at which this proc was last scheduled */ /* for schedulability testing */ - vlong testDelta; - int testtype; /* Release or Deadline */ - vlong testtime; + long testDelta; + int testtype; /* Release or Deadline */ + long testtime; Proc *testnext; /* other */ ushort flags; Timer; /* Stats */ - vlong edfused; - vlong extraused; - vlong aged; + long edfused; + long extraused; + long aged; ulong periods; ulong missed; }; /n/sourcesdump/2006/0128/plan9/sys/src/9/port/edf.h:45,51 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/edf.h:46,52 extern Lock edftestlock; /* for atomic admitting/expelling */ - #pragma varargck type "t" vlong + #pragma varargck type "t" long #pragma varargck type "U" uvlong /* Interface: */ [rsc] --rw-rw-r-- M 1428987 glenda sys 479 Jan 28 12:30 sys/src/9/port/master /n/sourcesdump/2006/0128/plan9/sys/src/9/port/master:9,15 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/master:9,14 D ssl E sdp F flash - F tinyfs I ip K kprof L lpt /n/sourcesdump/2006/0128/plan9/sys/src/9/port/master:20,26 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/master:19,24 U usb V lml V tv - X loopback Y pccard a tls b irq /n/sourcesdump/2006/0128/plan9/sys/src/9/port/master:43,49 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/master:41,46 w wd y i82365 y pcmcia - z mntstats | pipe ¤ cap κ kbmap [rsc] --rw-rw-r-- M 1428987 glenda sys 28053 Jan 28 12:29 sys/src/9/port/proc.c /n/sourcesdump/2006/0128/plan9/sys/src/9/port/proc.c:776,781 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/proc.c:776,783 if(up->notepending) { up->notepending = 0; splx(s); + if(up->procctl == Proc_exitme && up->closingfgrp) + forceclosefgrp(); error(Eintr); } /n/sourcesdump/2006/0128/plan9/sys/src/9/port/proc.c:1320,1326 - /n/sourcesdump/2006/0129/plan9/sys/src/9/port/proc.c:1322,1329 p->nerrlab = 0; p->slash = up->slash; p->dot = up->dot; - incref(p->dot); + if(p->dot) + incref(p->dot); memmove(p->note, up->note, sizeof(p->note)); p->nnote = up->nnote; [rsc] --rw-rw-r-- M 1428987 presotto sys 19884 Jan 28 12:31 sys/src/9/ppc/devflash.c /n/sourcesdump/2006/0128/plan9/sys/src/9/ppc/devflash.c:813,819 - /n/sourcesdump/2006/0129/plan9/sys/src/9/ppc/devflash.c:813,819 * If someone learns better, please email me, though * I doubt it will be much faster. - presotto@bell-labs.com */ - static ulong + static long ise_wbwrite(Flash *flash, Fword *p, int n, ulong off, ulong baddr, ulong *status) { Fword x; [rsc] --rw-rw-r-- M 1428987 presotto sys 17084 Jan 28 12:31 sys/src/9/ppc/trap.c /n/sourcesdump/2006/0128/plan9/sys/src/9/ppc/trap.c:225,232 - /n/sourcesdump/2006/0129/plan9/sys/src/9/ppc/trap.c:225,234 if(!user) panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1); syscall(ureg); - if (up->delaysched) + if (up->delaysched){ sched(); + splhi(); + } kexit(ureg); return; /* syscall() calls notify itself, don't do it again */ [jmk] --rw-rw-r-- M 1428987 glenda sys 13489 Jan 28 13:22 sys/src/9/port/edf.c [jmk] --rw-rw-r-- M 1428987 glenda bitsy 5941 Jan 28 21:12 sys/src/9/bitsy/dat.h /n/sourcesdump/2006/0128/plan9/sys/src/9/bitsy/dat.h:32,37 - /n/sourcesdump/2006/0129/plan9/sys/src/9/bitsy/dat.h:32,41 */ #define AOUT_MAGIC (E_MAGIC) + enum { + Lockcycles = 0, /* Don't measure lock latencies */ + }; + struct Lock { ulong key; /n/sourcesdump/2006/0128/plan9/sys/src/9/bitsy/dat.h:40,45 - /n/sourcesdump/2006/0129/plan9/sys/src/9/bitsy/dat.h:44,50 Proc *p; Mach *m; ushort isilock; + uvlong lockcycles; /* Measure lock latencies */ }; struct Label [jmk] --rw-rw-r-- M 1428987 glenda bitsy 16830 Jan 28 21:10 sys/src/9/bitsy/devflash.c /n/sourcesdump/2006/0128/plan9/sys/src/9/bitsy/devflash.c:728,734 - /n/sourcesdump/2006/0129/plan9/sys/src/9/bitsy/devflash.c:728,734 * If someone learns better, please email me, though * I doubt it will be much faster. - presotto@bell-labs.com */ - static ulong + static int ise_wbwrite(ulong *p, int n, ulong off, ulong baddr, ulong *status) { ulong x, start;