From 4e2e06df47b7a83960b79eba7db5ee0e909f21ca Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 18 Feb 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-02-18 --- pc/archgeneric.c | 2 +- pc/clock.c | 2 + pc/main.c | 1 - port/devcons.c | 169 +++++++++++++++++++++++++++++++++++++++++++---- port/lib.h | 1 + port/portfns.h | 1 + 6 files changed, 162 insertions(+), 14 deletions(-) diff --git a/pc/archgeneric.c b/pc/archgeneric.c index 03332fb422bf48c1286580440e45a0f79a6c2eb2..3b98688058457a152f57f8ce80f80e1751dda963 100644 --- a/pc/archgeneric.c +++ b/pc/archgeneric.c @@ -211,7 +211,7 @@ void cycletimerinit(void) { wrmsr(0x10, 0); - fasthz = 1000000LL*m->cpumhz; + fasthz = m->cpuhz; } /* diff --git a/pc/clock.c b/pc/clock.c index badb51957bf4a25003a0d4ceee89a77135c9a101..abf42626ed78b1f27752b2114dba8b68da0df7dc 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -38,9 +38,11 @@ clockintr(Ureg* ureg, void*) { Clock0link *lp; + fastticks(nil); m->ticks++; if(m->proc) m->proc->pc = ureg->pc; + fixtod(); accounttime(); if(kproftimer != nil) diff --git a/pc/main.c b/pc/main.c index fbcd89fec20378e60ea12b2859fe642e15bc8591..05ec5e70a27ba27eef89db2b17f590023c47aea2 100644 --- a/pc/main.c +++ b/pc/main.c @@ -153,7 +153,6 @@ main(void) kbdinit(); if(arch->clockenable) arch->clockenable(); -print("arch %s\n", arch->id); procinit0(); initseg(); links(); diff --git a/port/devcons.c b/port/devcons.c index 69cec5d75e0b6c2eb4aab78974b54eef3f75ae78..d191dc4f32eed1858f586c91c2228b374df609cc 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -350,6 +350,7 @@ enum{ Qhostdomain, Qhostowner, Qmsec, + Qnsec, Qnull, Qpgrpid, Qpid, @@ -378,6 +379,7 @@ static Dirtab consdir[]={ "hz", {Qhz}, NUMSIZE, 0666, "key", {Qkey}, DESKEYLEN, 0622, "msec", {Qmsec}, NUMSIZE, 0444, + "nsec", {Qnsec}, NUMSIZE, 0664, "null", {Qnull}, 0, 0666, "pgrpid", {Qpgrpid}, NUMSIZE, 0444, "pid", {Qpid}, NUMSIZE, 0444, @@ -393,10 +395,111 @@ static Dirtab consdir[]={ ulong boottime; /* seconds since epoch at boot */ +struct +{ + Lock; + vlong hz; /* frequency of fast clock */ + vlong last; /* last reading of fast clock */ + vlong off; /* offset from epoch to last */ + vlong lastns; /* last return value from gettod */ + vlong bias; /* current bias */ + vlong delta; /* amount to add to bias each slow clock tick */ + int n; /* number of times to add in delta */ + int i; /* number of times we've added in delta */ +} tod; + +void +settod(vlong now, vlong delta, int n) +{ + ilock(&tod); + tod.last = fastticks(nil); + tod.off = now; + tod.delta = delta; + tod.n = n; + tod.i = 0; + iunlock(&tod); +} + +// largest vlong devided by 10, 100, ... +static vlong vlmax[9] = { + 9223372036LL, + 92233720368LL, + 922337203685LL, + 9223372036854LL, + 92233720368547LL, + 922337203685477LL, + 9223372036854775LL, + 92233720368547758LL, + 922337203685477580LL, +}; +static vlong vlmult[9] = { + 1000000000LL, + 100000000LL, + 10000000LL, + 1000000LL, + 100000LL, + 10000LL, + 1000LL, + 100LL, + 10LL, +}; + +vlong +gettod(void) +{ + vlong x; + int i; + + ilock(&tod); + if(tod.hz == 0) + x = fastticks((uvlong*)&tod.hz); + else + x = fastticks(nil); + x -= tod.last; + + /* convert to nanoseconds */ + for(i = 0; i < 9; i++) + if(x < vlmax[i]){ + x *= vlmult[i]; + break; + } + x /= tod.hz; + if(i > 0) + x *= vlmult[9-i]; + + /* convert to epoch */ + x += tod.off; + + /* add in bias */ + x += tod.bias; + + if(x < tod.lastns) + x = tod.lastns; + tod.lastns = x; + iunlock(&tod); + + return x; +} + +void +fixtod(void) +{ + ilock(&tod); + if(tod.n > tod.i) + tod.bias += tod.delta; + iunlock(&tod); +} + long seconds(void) { - return boottime + TK2SEC(MACHP(0)->ticks); + vlong x; + int i; + + x = gettod(); + x /= 1000000000LL; + i = x; + return i; } int @@ -512,8 +615,8 @@ consread(Chan *c, void *buf, long n, vlong off) char tmp[128]; /* must be >= 6*NUMSIZE */ char *cbuf = buf; int ch, i, k, id, eol; - vlong offset = off; - uvlong ticks, fasthz; + vlong offset = off, x; + uvlong ticks; if(n <= 0) return n; @@ -603,9 +706,6 @@ consread(Chan *c, void *buf, long n, vlong off) case Qppid: return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE); - case Qtime: - return readnum((ulong)offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), 12); - case Qclock: k = offset; if(k >= 2*NUMSIZE) @@ -618,7 +718,10 @@ consread(Chan *c, void *buf, long n, vlong off) return n; case Qfastclock: - ticks = fastticks(&fasthz); + if(tod.hz == 0L) + ticks = fastticks((uvlong*)&tod.hz); + else + ticks = fastticks(nil); k = offset; if(k >= 4*NUMSIZE) @@ -626,7 +729,7 @@ consread(Chan *c, void *buf, long n, vlong off) if(k+n > 4*NUMSIZE) n = 4*NUMSIZE - k; readvlnum(0, tmp, 2*NUMSIZE, ticks, 2*NUMSIZE); - readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, fasthz, 2*NUMSIZE); + readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, tod.hz, 2*NUMSIZE); memmove(buf, tmp+k, n); return n; @@ -654,8 +757,21 @@ consread(Chan *c, void *buf, long n, vlong off) case Qnull: return 0; + case Qnsec: + x = gettod(); + return readvlnum((ulong)offset, buf, n, x, 2*NUMSIZE); + case Qmsec: - return readnum((ulong)offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE); + x = gettod(); + x /= 1000000LL; + i = x; + return readnum((ulong)offset, buf, n, i, NUMSIZE); + + case Qtime: + x = gettod(); + x /= 1000000000LL; + i = x; + return readnum((ulong)offset, buf, n, i, NUMSIZE); case Qhz: return readnum((ulong)offset, buf, n, HZ, NUMSIZE); @@ -731,6 +847,7 @@ conswrite(Chan *c, void *va, long n, vlong off) int id, fd; Chan *swc; ulong offset = off; + vlong f, nsec, delta; switch(c->qid.path){ case Qcons: @@ -781,9 +898,37 @@ conswrite(Chan *c, void *va, long n, vlong off) return 0; if(n >= sizeof cbuf) n = sizeof cbuf - 1; - memmove(cbuf, a, n); - cbuf[n-1] = 0; - boottime = strtoul(a, 0, 0)-TK2SEC(MACHP(0)->ticks); + strncpy(cbuf, a, n); + cbuf[n] = 0; + nsec = strtol(cbuf, 0, 0); + nsec *= 1000000000LL; + settod(nsec, 0, 0); + break; + + case Qfastclock: + if(n<=0 || !iseve()) + return 0; + if(n >= sizeof(cbuf)) + n = sizeof(cbuf)-1; + strncpy(cbuf, a, n); + cbuf[n] = 0; + f = strtovl(cbuf, 0, 0); + if(f <= 0L) + error(Ebadarg); + tod.hz = f; + break; + + case Qnsec: + if(n<=0 || !iseve()) + return 0; + if(n >= sizeof cbuf) + n = sizeof cbuf - 1; + strncpy(cbuf, a, n); + cbuf[n] = 0; + nsec = strtovl(cbuf, &a, 0); + delta = strtovl(a, &a, 0); + n = strtol(a, &a, 0); + settod(nsec, delta, n); break; case Qkey: diff --git a/port/lib.h b/port/lib.h index 93a308d1147d30f1e1702698053c8fd9b05eb8ac..525ceff4bc11842a9ffb5a6a20a50f61965b843d 100644 --- a/port/lib.h +++ b/port/lib.h @@ -68,6 +68,7 @@ extern int print(char*, ...); */ extern long strtol(char*, char**, int); extern ulong strtoul(char*, char**, int); +extern vlong strtovl(char*, char**, int); extern char etext[]; extern char edata[]; extern char end[]; diff --git a/port/portfns.h b/port/portfns.h index 28e4da6fca9ea5a4216006116333fcd6f28efcc7..c9d0d7f96055147ba5f728a3e0621a0e46249ac7 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -96,6 +96,7 @@ int fault(ulong, int); void fdclose(int, int); Chan* fdtochan(int, int, int, int); int fixfault(Segment*, ulong, int, int); +void fixtod(void); void flushmmu(void); void forkchild(Proc*, Ureg*); void forkret(void);