commit c3459537577cb76e83a16e40f47c5e66f6277a22 Author: Russ Cox Date: Tue Mar 11 11:41:24 2025 -0400 sys/src/9k: add monotonic time support Same as previous change in sys/src/9. diff --git a/sys/src/9k/k10/syscall.c b/sys/src/9k/k10/syscall.c index 519ad7f6..329906b8 100755 --- a/sys/src/9k/k10/syscall.c +++ b/sys/src/9k/k10/syscall.c @@ -226,7 +226,7 @@ syscall(int scallnr, Ureg* ureg) startns = 0; if(up->trace && (pt = proctrace) != nil) - pt(up, STrap, todget(nil), STrapSC|scallnr); + pt(up, STrap, todget(nil, nil), STrapSC|scallnr); if(up->procctl == Proc_tracesyscall){ /* @@ -245,7 +245,7 @@ syscall(int scallnr, Ureg* ureg) if(up->syscalltrace) free(up->syscalltrace); up->syscalltrace = nil; - startns = todget(nil); + startns = todget(nil, nil); } if(scallnr == RFORK) @@ -297,7 +297,7 @@ syscall(int scallnr, Ureg* ureg) ureg->ax = ar0.p; if(up->procctl == Proc_tracesyscall){ - stopns = todget(nil); + stopns = todget(nil, nil); up->procctl = Proc_stopme; sysretfmt(scallnr, (va_list)(sp+BY2V), &ar0, startns, stopns); s = splhi(); diff --git a/sys/src/9k/port/devcons.c b/sys/src/9k/port/devcons.c index e6162d68..103e632f 100755 --- a/sys/src/9k/port/devcons.c +++ b/sys/src/9k/port/devcons.c @@ -1228,7 +1228,7 @@ rand(void) static uvlong uvorder = 0x0001020304050607ULL; static uchar* -le2vlong(vlong *to, uchar *f) +be2vlong(vlong *to, uchar *f) { uchar *t, *o; int i; @@ -1241,7 +1241,7 @@ le2vlong(vlong *to, uchar *f) } static uchar* -vlong2le(uchar *t, vlong from) +vlong2be(uchar *t, vlong from) { uchar *f, *o; int i; @@ -1256,7 +1256,7 @@ vlong2le(uchar *t, vlong from) static long order = 0x00010203; static uchar* -le2long(long *to, uchar *f) +be2long(long *to, uchar *f) { uchar *t, *o; int i; @@ -1268,19 +1268,6 @@ le2long(long *to, uchar *f) 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"; /* @@ -1291,19 +1278,20 @@ char *Ebadtimectl = "bad time control"; 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); } @@ -1337,23 +1325,27 @@ static int 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; @@ -1378,20 +1370,20 @@ writebintime(char *buf, int n) 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); todsetfreq(fasthz); break; } diff --git a/sys/src/9k/port/devproc.c b/sys/src/9k/port/devproc.c index c64e8eb2..46d02926 100755 --- a/sys/src/9k/port/devproc.c +++ b/sys/src/9k/port/devproc.c @@ -280,7 +280,7 @@ _proctrace(Proc* p, Tevent etype, vlong ts, vlong) te->pid = p->pid; te->etype = etype; if (ts == 0) - te->time = todget(nil); + te->time = todget(nil, nil); else te->time = ts; tproduced++; diff --git a/sys/src/9k/port/devptrace.c b/sys/src/9k/port/devptrace.c index ebfd5e0f..ccfd1cc1 100755 --- a/sys/src/9k/port/devptrace.c +++ b/sys/src/9k/port/devptrace.c @@ -65,7 +65,7 @@ _ptrace(Proc *p, int etype, vlong ts, vlong arg) return; } if(ts == 0) - ts = todget(nil); + ts = todget(nil, nil); i = (tproduced&ntmask) * PTsize; te = &tevents[i]; PBIT32(te, (int)p->pid); diff --git a/sys/src/9k/port/edf.c b/sys/src/9k/port/edf.c index 7e785ba2..b6587b4c 100755 --- a/sys/src/9k/port/edf.c +++ b/sys/src/9k/port/edf.c @@ -198,7 +198,7 @@ release(Proc *p) DPRINT("%lud release %d[%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); + nowns = todget(nil, nil); pt(p, SRelease, nowns, 0); pt(p, SDeadline, nowns + 1000LL*e->D, 0); } @@ -327,7 +327,7 @@ edfrun(Proc *p, int edfpri) DPRINT("v"); } if(p->trace && (pt = proctrace)) - pt(p, SInte, todget(nil) + e->tns, 0); + pt(p, SInte, todget(nil, nil) + e->tns, 0); e->tmode = Trelative; e->tf = deadlineintr; e->ta = p; diff --git a/sys/src/9k/port/portfns.h b/sys/src/9k/port/portfns.h index 470edba5..8ae59771 100755 --- a/sys/src/9k/port/portfns.h +++ b/sys/src/9k/port/portfns.h @@ -329,7 +329,7 @@ void timerset(uvlong); 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); diff --git a/sys/src/9k/port/sysproc.c b/sys/src/9k/port/sysproc.c index 31cee7d5..5366fc81 100755 --- a/sys/src/9k/port/sysproc.c +++ b/sys/src/9k/port/sysproc.c @@ -1215,5 +1215,5 @@ syssemrelease(Ar0* ar0, va_list list) void sysnsec(Ar0* ar0, va_list) { - ar0->vl = todget(nil); + ar0->vl = todget(nil, nil); } diff --git a/sys/src/9k/port/taslock.c b/sys/src/9k/port/taslock.c index b59036d0..f65ef099 100755 --- a/sys/src/9k/port/taslock.c +++ b/sys/src/9k/port/taslock.c @@ -82,7 +82,7 @@ lock(Lock *l) */ print("inversion %#p pc %#p proc %d held by pc %#p proc %d\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 */ + up->edf->d = todget(nil, nil); /* yield to process with lock */ } if(i++ > 100000000){ i = 0; diff --git a/sys/src/9k/port/tod.c b/sys/src/9k/port/tod.c index 247d5a25..df639485 100755 --- a/sys/src/9k/port/tod.c +++ b/sys/src/9k/port/tod.c @@ -3,6 +3,7 @@ #include "mem.h" #include "dat.h" #include "fns.h" +#include "../port/error.h" /* * Compute nanosecond epoch time from the fastest ticking clock @@ -43,7 +44,9 @@ struct { 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; /* ... */ @@ -60,20 +63,43 @@ todinit(void) 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); } +/* + * 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 */ @@ -124,10 +150,10 @@ todset(vlong t, vlong delta, int n) * 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) @@ -158,16 +184,21 @@ todget(vlong *ticksp) 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; } @@ -218,7 +249,7 @@ if(x > 30000000000ULL) iprint("todfix %llud\n", x); long seconds(void) { - return (vlong)todget(nil) / TODFREQ; + return (vlong)todget(nil, nil) / TODFREQ; } uvlong