shithub: orca

Download patch

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++;