bin/120813: grdc(6) off by 500 ms (on average)

Martin Kammerhofer dada at pluto.tugraz.at
Mon Feb 18 18:00:07 UTC 2008


>Number:         120813
>Category:       bin
>Synopsis:       grdc(6) off by 500 ms (on average)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 18 18:00:06 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Martin Kammerhofer
>Release:        FreeBSD 6.3-STABLE i386
>Organization:
TUG
>Environment:
System: FreeBSD Martin.liebt.Susi 6.3-STABLE FreeBSD 6.3-STABLE #1: Fri Feb 1 09:10:38 CET 2008 toor at Martin.liebt.Susi:/usr/obj/usr/src/sys/P2B-S i386
>Description:
	The grdc(6) program (grand digital clock) draws (with curses) a
	digital clock and refreshes the display once per second.
	It uses sleep(1) in the main loop. Therefore the displayed clock
	will be late by _off_, with 0 <= _off_ < 1 second.
	On averagE it will be late half a second.
	This is quite noticeable.
>How-To-Repeat:
	Run /usr/games/grdc in an xterm window alongside a
	xclock -update 1
	and watch!
>Fix:
--- grdc.c.orig	2008-02-06 20:21:46.000000000 +0100
+++ grdc.c	2008-02-06 20:24:32.000000000 +0100
@@ -14,6 +14,7 @@
  * $FreeBSD: src/games/grdc/grdc.c,v 1.12 2003/06/23 16:02:40 will Exp $
  */
 
+#include <sys/time.h>
 #include <err.h>
 #include <time.h>
 #include <signal.h>
@@ -55,9 +56,7 @@
 }
 
 int
-main(argc, argv)
-int argc;
-char **argv;
+main (int argc, char **argv)
 {
 long t, a;
 int i, j, s, k;
@@ -65,11 +64,16 @@
 int ch;
 int scrol;
 int t12;
+int dflag = 0;
+struct timeval tv;
 
 	t12 = scrol = 0;
 
-	while ((ch = getopt(argc, argv, "ts")) != -1)
+	while ((ch = getopt(argc, argv, "dts")) != -1)
 	switch (ch) {
+	case 'd':
+		dflag++;
+		break;
 	case 's':
 		scrol = 1;
 		break;
@@ -138,7 +142,12 @@
 	}
 	do {
 		mask = 0;
-		time(&now);
+		if (gettimeofday(&tv, NULL))
+			err(2, "gettimeofday");
+		if (dflag)
+			warnx("woke up @ %ld.%06ld\n",
+			      (long)tv.tv_sec, (long)tv.tv_usec);
+		now = tv.tv_sec;
 		tm = localtime(&now);
 		set(tm->tm_sec%10, 0);
 		set(tm->tm_sec/10, 4);
@@ -193,7 +202,10 @@
 		}
 		movto(6, 0);
 		refresh();
-		sleep(1);
+		if (gettimeofday(&tv, NULL))
+			err(2, "gettimeofday");
+		if (tv.tv_sec == now)
+			usleep(1000000 - tv.tv_usec);
 		if (sigtermed) {
 			standend();
 			clear();

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list