Quoth Russ Cox <[email protected]>:
> 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*)ℴ
- 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