ref: 571642871a97fae24b21fbb268f03cc1778ed6c0
parent: c593c3b2d5009c798486cdd3745ff0e160aeeeb6
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Feb 15 12:01:49 EST 2020
plan9: nanosec: handle wrap-around, increase precision
--- a/plan9.c
+++ b/plan9.c
@@ -216,16 +216,18 @@
*
* "fasthz" is how many ticks there are in a second
* can be read from /dev/time
+ *
+ * perhaps using RDTSCP is even better
*/
static uvlong
nanosec(void)
{
- static double fasthz = 0.0;
- uvlong x;
+ static uvlong fasthz, xstart;
+ uvlong x, div;
int f, n, i;
char tmp[128], *e;
- if (fasthz < 1.0) {
+ if (fasthz < 1) {
if ((f = open("/dev/time", OREAD)) < 0)
sysfatal("failed to open /dev/time");
if ((n = read(f, tmp, sizeof(tmp)-1)) < 2)
@@ -234,21 +236,30 @@
e = tmp;
for (i = 0; i < 3; i++)
strtoll(e, &e, 10);
- fasthz = strtod(e, nil);
- if (fasthz < 1.0)
+ fasthz = strtoll(e, nil, 10);
+ if (fasthz < 1)
sysfatal("failed to read fasthz");
close(f);
+ cycles(&xstart);
}
cycles(&x);
- return (double)x / (fasthz / 1000000000.0);
+ if (x < xstart) { /* wrap around */
+ xstart = 0;
+ x += 0 - xstart;
+ }
+ x -= xstart;
+
+ for (div = 1000000000ULL; x < 0x1999999999999999ULL && div > 1 ; div /= 10ULL, x *= 10ULL);
+
+ return x / (fasthz / div);
}
static void
orcathread(void *drawchan)
{
- vlong start, end, n, oldn;
+ vlong start, end, n;
vlong processold, processnew;
- int w, h, oldbpm, fd;
+ int w, h, fd;
char tmp[64];
threadsetname("orca/sim");
@@ -273,21 +284,13 @@
process(&events);
nbsendul(drawchan, 0);
- oldn = start;
- end = start + 1;
- oldbpm = 0;
forward = 0;
- for (n = start; !forward && (pause || n < end); n = nanosec()) {
- if (bpm != oldbpm) {
- end = start + 15000000000LL/bpm; /* 10^9 * 60 / 4 */
- oldbpm = bpm;
- }
-
- /* not supposed to jump back, but just in case, do _something_ */
- if (n < oldn)
- end -= oldn - n;
-
- oldn = n;
+ do {
+ end = 15000000000LL/bpm; /* 1e9*60/4 */
+ n = nanosec() - start;
+ if (n >= end && !pause)
+ break;
+ /* unpause is not precise at all */
if (pause || end - n > 750000000LL)
sleep(70);
else if (end - n > 25000000LL)
@@ -294,7 +297,7 @@
sleep(20);
else if (end - n > 10000000LL)
sleep(1);
- }
+ } while (!forward);
framedev = (processnew - processold - 15000000000LL/bpm)/1000000LL;
tick++;