Quoth Russ Cox <r...@swtch.com>:
> As far as the top-of-stack info, it gets complicated. You have to hard-code
> an algorithm that must be implemented in every user binary, and then it's a
> pain to change. This is why in Go we've backed away from reading that info
> on Mac and why we call into the VDSO on Linux instead of recreating that
> code ourselves. Personally, I'm not too worried about the cost of fetching
> the time. A system call is fine.
> 
> Based on this discussion, I've abandoned the idea of changing the system
> calls, and I've updated Go to open /dev/bintime at startup and abandon
> nsec. It also opens /dev/random at startup now too. If we're opening one,
> two is not a big deal. That change is pending at https://go.dev/cl/656755.
> 
> However, a change to Plan 9 is still needed to provide monotonic time. At
> first I was going to try to recreate it from the ticks and fasthz values in
> /dev/bintime, but the value of fasthz can change over time as aux/timesync
> deems it necessary, and if fasthz goes up, then 1e9*ticks/fasthz will go
> down, making the derived time non-monotonic. It is also annoying to do that
> calculation efficiently: more parameters are needed from the kernel.
> Instead of exposing all those parameters, it is far easier and cleaner to
> have the kernel maintain a monotonic time and simply expose that. I suggest
> we add the monotonic time in nanoseconds as an extra field you can read
> from /dev/time and /dev/bintime. If you ask for a big enough buffer, you
> get it. If not, you don't. The diff is here:
> https://github.com/rsc/plan9/commit/baf076425c.
> 
> Best,
> Russ

Alright, here's a draft of a parallel change for 9front.

This also makes a related semantic change -- While we're
touching all of the todget calls, it seems like it'd be
sensible to trace our syscalls and edf deadlines using
monotonic timestamps too.

diff 6c59f4960d2641786557499443e6cdb5e250d064 uncommitted
--- a/sys/src/9/arm64/trap.c
+++ b/sys/src/9/arm64/trap.c
@@ -221,7 +221,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
                
                if(scallnr >= nsyscall || systab[scallnr] == nil){
@@ -244,7 +244,7 @@
        }
        ureg->r0 = ret;
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/cycv/trap.c
+++ b/sys/src/9/cycv/trap.c
@@ -233,7 +233,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
                
                if(scallnr >= nsyscall || systab[scallnr] == nil){
@@ -257,7 +257,7 @@
        
        ureg->r0 = ret;
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/kw/syscall.c
+++ b/sys/src/9/kw/syscall.c
@@ -186,7 +186,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
                if(scallnr >= nsyscall || systab[scallnr] == nil){
                        postnote(up, 1, "sys: bad sys call", NDebug);
@@ -218,7 +218,7 @@
        ureg->r0 = ret;
 
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/mt7688/syscall.c
+++ b/sys/src/9/mt7688/syscall.c
@@ -53,7 +53,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
 
                if(scallnr >= nsyscall || systab[scallnr] == nil){
@@ -89,7 +89,7 @@
        ureg->r1 = ret;
 
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/pc/devlml.c
+++ b/sys/src/9/pc/devlml.c
@@ -396,7 +396,7 @@
                statcom = lml->codedata->statCom[fno];
                jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr + 2);
                jpgheader->frameNo = lml->jpgframeno;
-               jpgheader->ftime  = todget(nil);
+               jpgheader->ftime  = todget(nil, nil);
                jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
                jpgheader->frameSeqNo = statcom >> 24;
                wakeup(&lml->sleepjpg);
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -493,7 +493,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
 
                if(scallnr >= nsyscall || systab[scallnr] == nil){
@@ -528,7 +528,7 @@
        ureg->ax = ret;
 
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -472,7 +472,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
                if(scallnr >= nsyscall || systab[scallnr] == nil){
                        postnote(up, 1, "sys: bad sys call", NDebug);
@@ -504,7 +504,7 @@
        }
 
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/port/devcons.c
+++ b/sys/src/9/port/devcons.c
@@ -817,7 +817,7 @@
 static uvlong uvorder = 0x0001020304050607ULL;
 
 static uchar*
-le2vlong(vlong *to, uchar *f)
+be2vlong(vlong *to, uchar *f)
 {
        uchar *t, *o;
        int i;
@@ -830,7 +830,7 @@
 }
 
 static uchar*
-vlong2le(uchar *t, vlong from)
+vlong2be(uchar *t, vlong from)
 {
        uchar *f, *o;
        int i;
@@ -845,7 +845,7 @@
 static long order = 0x00010203;
 
 static uchar*
-le2long(long *to, uchar *f)
+be2long(long *to, uchar *f)
 {
        uchar *t, *o;
        int i;
@@ -857,19 +857,6 @@
        return f+sizeof(long);
 }
 
-static uchar*
-long2le(uchar *t, long from)
-{
-       uchar *f, *o;
-       int i;
-
-       f = (uchar*)&from;
-       o = (uchar*)&order;
-       for(i = 0; i < sizeof(long); i++)
-               t[i] = f[o[i]];
-       return t+sizeof(long);
-}
-
 char *Ebadtimectl = "bad time control";
 
 /*
@@ -880,19 +867,20 @@
 static int
 readtime(ulong off, char *buf, int n)
 {
-       vlong   nsec, ticks;
+       vlong   nsec, ticks, mono;
        long sec;
-       char str[7*NUMSIZE];
+       char str[9*NUMSIZE];
 
-       nsec = todget(&ticks);
+       nsec = todget(&ticks, &mono);
        if(fasthz == 0LL)
                fastticks((uvlong*)&fasthz);
        sec = nsec/1000000000ULL;
-       snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
+       snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud %*llud ",
                NUMSIZE-1, sec,
                VLNUMSIZE-1, nsec,
                VLNUMSIZE-1, ticks,
-               VLNUMSIZE-1, fasthz);
+               VLNUMSIZE-1, fasthz,
+               VLNUMSIZE-1, mono);
        return readstr(off, buf, n, str);
 }
 
@@ -926,23 +914,27 @@
 readbintime(char *buf, int n)
 {
        int i;
-       vlong nsec, ticks;
+       vlong nsec, ticks, mono;
        uchar *b = (uchar*)buf;
 
        i = 0;
        if(fasthz == 0LL)
                fastticks((uvlong*)&fasthz);
-       nsec = todget(&ticks);
+       nsec = todget(&ticks, &mono);
+       if(n >= 4*sizeof(uvlong)){
+               vlong2be(b+3*sizeof(uvlong), mono);
+               i += sizeof(uvlong);
+       }
        if(n >= 3*sizeof(uvlong)){
-               vlong2le(b+2*sizeof(uvlong), fasthz);
+               vlong2be(b+2*sizeof(uvlong), fasthz);
                i += sizeof(uvlong);
        }
        if(n >= 2*sizeof(uvlong)){
-               vlong2le(b+sizeof(uvlong), ticks);
+               vlong2be(b+sizeof(uvlong), ticks);
                i += sizeof(uvlong);
        }
        if(n >= 8){
-               vlong2le(b, nsec);
+               vlong2be(b, nsec);
                i += sizeof(vlong);
        }
        return i;
@@ -968,20 +960,20 @@
        case 'n':
                if(n < sizeof(vlong))
                        error(Ebadtimectl);
-               le2vlong(&delta, p);
+               be2vlong(&delta, p);
                todset(delta, 0, 0);
                break;
        case 'd':
                if(n < sizeof(vlong)+sizeof(long))
                        error(Ebadtimectl);
-               p = le2vlong(&delta, p);
-               le2long(&period, p);
+               p = be2vlong(&delta, p);
+               be2long(&period, p);
                todset(-1, delta, period);
                break;
        case 'f':
                if(n < sizeof(uvlong))
                        error(Ebadtimectl);
-               le2vlong(&fasthz, p);
+               be2vlong(&fasthz, p);
                if(fasthz <= 0)
                        error(Ebadtimectl);
                todsetfreq(fasthz);
--- a/sys/src/9/port/devloopback.c
+++ b/sys/src/9/port/devloopback.c
@@ -553,7 +553,7 @@
        bp = padblock(bp, Tmsize);
        if(BLEN(bp) < lb->minmtu)
                bp = adjustblock(bp, lb->minmtu);
-       ptime(bp->rp, todget(nil));
+       ptime(bp->rp, todget(nil, nil));
 
        link->packets++;
        link->bytes += n;
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -281,7 +281,7 @@
        te->pid = p->pid;
        te->etype = etype;
        if (ts == 0)
-               te->time = todget(nil);
+               todget(nil, &te->time);
        else
                te->time = ts;
        tproduced++;
--- a/sys/src/9/port/edf.c
+++ b/sys/src/9/port/edf.c
@@ -195,7 +195,7 @@
                DPRINT("%lud release %lud[%s], r=%lud, d=%lud, t=%lud, 
S=%lud\n",
                        now, p->pid, statename[p->state], e->r, e->d, e->t, 
e->S);
                if(pt = proctrace){
-                       nowns = todget(nil);
+                       todget(nil, &nowns);
                        pt(p, SRelease, nowns);
                        pt(p, SDeadline, nowns + 1000LL*e->D);
                }
@@ -291,6 +291,7 @@
        Edf *e;
        void (*pt)(Proc*, int, vlong);
        long tns;
+       vlong tnow;
 
        e = p->edf;
        /* Called with edflock held */
@@ -315,8 +316,10 @@
                }else{
                        DPRINT("v");
                }
-               if(p->trace && (pt = proctrace))
-                       pt(p, SInte, todget(nil) + e->tns);
+               if(p->trace && (pt = proctrace)){
+                       todget(nil, &tnow);
+                       pt(p, SInte, tnow + e->tns);
+               }
                e->tmode = Trelative;
                e->tf = deadlineintr;
                e->ta = p;
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -366,7 +366,7 @@
 ulong          tk2ms(ulong);
 #define                TK2MS(x) ((x)*(1000/HZ))
 uvlong         tod2fastticks(vlong);
-vlong          todget(vlong*);
+vlong          todget(vlong*, vlong*);
 void           todsetfreq(vlong);
 void           todinit(void);
 void           todset(vlong, vlong, int);
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -1257,12 +1257,12 @@
        /* return in register on 64bit machine */
        if(sizeof(uintptr) == sizeof(vlong)){
                USED(list);
-               return (uintptr)todget(nil);
+               return (uintptr)todget(nil, nil);
        }
 
        v = va_arg(list, vlong*);
        evenaddr((uintptr)v);
        validaddr((uintptr)v, sizeof(vlong), 1);
-       *v = todget(nil);
+       *v = todget(nil, nil);
        return 0;
 }
--- a/sys/src/9/port/taslock.c
+++ b/sys/src/9/port/taslock.c
@@ -36,6 +36,7 @@
 lock(Lock *l)
 {
        int i;
+       vlong mono;
        uintptr pc;
 
        pc = getcallerpc(&l);
@@ -67,7 +68,8 @@
                                 */
                                print("inversion %#p pc %#p proc %lud held by 
pc %#p proc %lud\n",
                                        l, pc, up ? up->pid : 0, l->pc, l->p ? 
l->p->pid : 0);
-                               up->edf->d = todget(nil);       /* yield to 
process with lock */
+                               todget(nil, &mono);     /* yield to process 
with lock */
+                               up->edf->d = mono;
                        }
                        if(i++ > 100000000){
                                i = 0;
--- a/sys/src/9/port/tod.c
+++ b/sys/src/9/port/tod.c
@@ -44,7 +44,9 @@
        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 */
+       vlong   off;            /* offset from epoch to last (ns) */
+       vlong   monolast;       /* last reading of fast clocks for monotonic 
time */
+       vlong   monooff;        /* offset from 0 to monolast (ns) */
        vlong   lasttime;       /* last return value from todget */
        vlong   delta;  /* add 'delta' each slow clock tick from sstart to send 
*/
        ulong   sstart;         /* ... */
@@ -61,6 +63,7 @@
        ilock(&tod);
        tod.init = 1;                   /* prevent reentry via fastticks */
        tod.last = fastticks((uvlong *)&tod.hz);
+       tod.monolast = tod.last;
        iunlock(&tod);
        todsetfreq(tod.hz);
        addclock0link(todfix, 100);
@@ -67,14 +70,36 @@
 }
 
 /*
+ *  return monotonic ns; tod must be locked
+ */
+static vlong
+todmono(vlong ticks)
+{
+       uvlong x;
+       vlong diff;
+
+       if(tod.hz == 0) /* called from first todsetfreq */
+               return 0;
+       diff = ticks - tod.monolast;
+       mul64fract(&x, diff, tod.multiplier);
+       x += tod.monooff;
+       return x;
+}
+
+/*
  *  calculate multiplier
  */
 void
 todsetfreq(vlong f)
 {
+       vlong ticks;
+
        if (f <= 0)
                panic("todsetfreq: freq %lld <= 0", f);
        ilock(&tod);
+       ticks = fastticks(nil);
+       tod.monooff = todmono(ticks);
+       tod.monolast = ticks;
        tod.hz = f;
 
        /* calculate multiplier for time conversion */
@@ -125,10 +150,10 @@
  *  get time of day
  */
 vlong
-todget(vlong *ticksp)
+todget(vlong *ticksp, vlong *monop)
 {
        uvlong x;
-       vlong ticks, diff;
+       vlong ticks, diff, mono;
        ulong t;
 
        if(!tod.init)
@@ -159,16 +184,21 @@
        mul64fract(&x, diff, tod.multiplier);
        x += tod.off;
 
-       /* time can't go backwards */
+       /* time can't go backwards (except when /dev/[bin]time is written) */
        if(x < tod.lasttime)
                x = tod.lasttime;
        else
                tod.lasttime = x;
 
+       mono = 0;
+       if(monop != nil)
+               mono = todmono(ticks);
        iunlock(&tod);
 
        if(ticksp != nil)
                *ticksp = ticks;
+       if(monop != nil)
+               *monop = mono;
 
        return x;
 }
@@ -219,7 +249,7 @@
 long
 seconds(void)
 {
-       return (vlong)todget(nil) / TODFREQ;
+       return (vlong)todget(nil, nil) / TODFREQ;
 }
 
 uvlong
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -595,7 +595,7 @@
                if(up->syscalltrace)
                        free(up->syscalltrace);
                up->syscalltrace = nil;
-               *startnsp = todget(nil);
+               todget(nil, startnsp);
        }
 }
 
@@ -602,12 +602,14 @@
 static void
 sctracefinish(ulong scallnr, ulong sp, int ret, vlong startns)
 {
+       vlong stopns;
        int s;
 
        if(up->procctl == Proc_tracesyscall){
+               todget(nil, &stopns);
                up->procctl = Proc_stopme;
                sysretfmt(scallnr, (va_list)(sp+BY2WD), ret,
-                       startns, todget(nil));
+                       startns, stopns);
                s = splhi();
                procctl();
                splx(s);
--- a/sys/src/9/teg2/syscall.c
+++ b/sys/src/9/teg2/syscall.c
@@ -202,7 +202,7 @@
 
        up->nerrlab = 0;
        ret = -1;
-       startns = todget(nil);
+       todget(nil, &startns);
 
        l1cache->wb();                  /* system is more stable with this */
        if(!waserror()){
@@ -240,7 +240,7 @@
        ureg->r0 = ret;
 
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list)(sp+BY2WD), ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -233,7 +233,7 @@
                        up->procctl = Proc_stopme;
                        procctl();
                        splx(s);
-                       startns = todget(nil);
+                       todget(nil, &startns);
                }
                if(scallnr >= nsyscall || systab[scallnr] == nil){
                        postnote(up, 1, "sys: bad sys call", NDebug);
@@ -256,7 +256,7 @@
        
        ureg->r0 = ret;
        if(up->procctl == Proc_tracesyscall){
-               stopns = todget(nil);
+               todget(nil, &stopns);
                sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
                s = splhi();
                up->procctl = Proc_stopme;


------------------------------------------
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/T59810df4fe34a033-M2c451362e4dff236d4dea432
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to