From dada@sbox.tugraz.at  Mon Feb 18 17:56:36 2008
Return-Path: <dada@sbox.tugraz.at>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id C6C0516A46B
	for <freebsd-gnats-submit@freebsd.org>; Mon, 18 Feb 2008 17:56:36 +0000 (UTC)
	(envelope-from dada@sbox.tugraz.at)
Received: from mailrelay.tugraz.at (mailrelay.tu-graz.ac.at [129.27.2.202])
	by mx1.freebsd.org (Postfix) with ESMTP id 6CD6113C46E
	for <freebsd-gnats-submit@freebsd.org>; Mon, 18 Feb 2008 17:56:36 +0000 (UTC)
	(envelope-from dada@sbox.tugraz.at)
Received: from webmail.tugraz.at (webmail.tu-graz.ac.at [129.27.2.204])
	by mailrelay2.tugraz.at (8.14.2/8.14.2) with ESMTP id m1IHCUYb029730
	for <freebsd-gnats-submit@freebsd.org>; Mon, 18 Feb 2008 18:12:30 +0100 (CET)
Received: from sbox.tugraz.at ([unix socket]) by sbox.tugraz.at (Cyrus
	v2.3.9-cyrus@sbox.tugraz.at) with LMTPA; Mon, 18 Feb 2008 18:11:26 +0100
Received: from mailrelay.tugraz.at (mailrelay.tu-graz.ac.at [129.27.2.202])
	by sbox.tugraz.at (8.14.2/8.14.2) with ESMTP id m1IHBQIH021332 for
	<dada@sbox.tugraz.at>; Mon, 18 Feb 2008 18:11:26 +0100 (CET)
Received: from pluto.tugraz.at (pluto.tu-graz.ac.at [129.27.3.200]) by
	mailrelay1.tugraz.at (8.14.2/8.14.2) with ESMTP id m1IHBPRU011352
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for
	<dada@sbox.tugraz.at>; Mon, 18 Feb 2008 18:11:25 +0100 (CET)
Received: from pluto.tugraz.at (localhost.localdomain [127.0.0.1]) by
	pluto.tugraz.at (8.13.8/8.13.8) with ESMTP id m1IHBHVj021494 for
	<dada@sbox.tugraz.at>; Mon, 18 Feb 2008 18:11:17 +0100
Received: (from dada@localhost) by pluto.tugraz.at (8.13.8/8.13.8/Submit)
	id m1IHBHI3021493 for dada@sbox.tugraz.at; Mon, 18 Feb 2008 18:11:17 +0100
Message-Id: <200802181711.m1IHBHI3021493@pluto.tugraz.at>
Date: Mon, 18 Feb 2008 18:11:17 +0100
From: Martin Kammerhofer <dada@pluto.tugraz.at>
To: dada@sbox.tugraz.at
Subject: grdc(6) off by 500 ms (on average)

>Number:         120813
>Category:       bin
>Synopsis:       [patch] grdc(6) off by 500 ms (on average)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    delphij
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 18 18:00:06 UTC 2008
>Closed-Date:    Fri Mar 12 00:51:51 UTC 2010
>Last-Modified:  Fri Mar 12 01:00:09 UTC 2010
>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@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:
State-Changed-From-To: open->patched 
State-Changed-By: delphij 
State-Changed-When: Wed Feb 10 18:20:30 UTC 2010 
State-Changed-Why:  
A different patch committed.  MFC reminder. 


Responsible-Changed-From-To: freebsd-bugs->delphij 
Responsible-Changed-By: delphij 
Responsible-Changed-When: Wed Feb 10 18:20:30 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=120813 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/120813: commit references a PR
Date: Wed, 10 Feb 2010 18:20:35 +0000 (UTC)

 Author: delphij
 Date: Wed Feb 10 18:20:20 2010
 New Revision: 203760
 URL: http://svn.freebsd.org/changeset/base/203760
 
 Log:
   Improve time precision for grdc(6):
   
   Traditionally, grdc would obtain time through time(3) which in turn gets
   only the second part of clock (CLOCK_SECOND), and sleep for 1 second after
   each screen refresh.
   
   This approach would have two problems.  First, we are not guaranteed to
   be waken up at the beginning of a whole second, which will typically
   exhibit as a "lag" on second number.  Second, because we sleep for whole
   second, and the refresh process would take some time, the error would
   accumulate from time to time, making the lag variable.
   
   Make grdc(6) to use time(3) to get time only at the beginning, and sample
   time in CLOCK_REALTIME_FAST granularity after refreshing, and use the
   nanosecond part to caculate how much time we want to sleep.
   
   PR:		bin/120813
   MFC after:	1 month
 
 Modified:
   head/games/grdc/grdc.c
 
 Modified: head/games/grdc/grdc.c
 ==============================================================================
 --- head/games/grdc/grdc.c	Wed Feb 10 17:02:06 2010	(r203759)
 +++ head/games/grdc/grdc.c	Wed Feb 10 18:20:20 2010	(r203760)
 @@ -59,6 +59,7 @@ main(argc, argv)
  int argc;
  char **argv;
  {
 +struct timespec ts;
  long t, a;
  int i, j, s, k;
  int n;
 @@ -136,9 +137,9 @@ int t12;
  
  		attrset(COLOR_PAIR(2));
  	}
 +	time(&now);
  	do {
  		mask = 0;
 -		time(&now);
  		tm = localtime(&now);
  		set(tm->tm_sec%10, 0);
  		set(tm->tm_sec/10, 4);
 @@ -193,7 +194,19 @@ int t12;
  		}
  		movto(6, 0);
  		refresh();
 -		sleep(1);
 +		clock_gettime(CLOCK_REALTIME_FAST, &ts);
 +		if (ts.tv_sec == now) {
 +			if (ts.tv_nsec > 0) {
 +				ts.tv_sec = 0;
 +				ts.tv_nsec = 1000000000 - ts.tv_nsec;
 +			} else {
 +				ts.tv_sec = 1;
 +				ts.tv_nsec = 0;
 +			}
 +			nanosleep(&ts, NULL);
 +			now = ts.tv_sec + 1;
 +		} else
 +			now = ts.tv_sec;
  		if (sigtermed) {
  			standend();
  			clear();
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: delphij 
State-Changed-When: Fri Mar 12 00:51:34 UTC 2010 
State-Changed-Why:  
Patch applied agasint 7 and 8-STABLE. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=120813 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/120813: commit references a PR
Date: Fri, 12 Mar 2010 00:51:26 +0000 (UTC)

 Author: delphij
 Date: Fri Mar 12 00:51:13 2010
 New Revision: 205056
 URL: http://svn.freebsd.org/changeset/base/205056
 
 Log:
   MFC r203760: Improve time precision for grdc(6):
   
   Traditionally, grdc would obtain time through time(3) which in turn gets
   only the second part of clock (CLOCK_SECOND), and sleep for 1 second after
   each screen refresh.
   
   This approach would have two problems.  First, we are not guaranteed to
   be waken up at the beginning of a whole second, which will typically
   exhibit as a "lag" on second number.  Second, because we sleep for whole
   second, and the refresh process would take some time, the error would
   accumulate from time to time, making the lag variable.
   
   Make grdc(6) to use time(3) to get time only at the beginning, and sample
   time in CLOCK_REALTIME_FAST granularity after refreshing, and use the
   nanosecond part to caculate how much time we want to sleep.
   
   PR:		bin/120813
 
 Modified:
   stable/8/games/grdc/grdc.c
 Directory Properties:
   stable/8/games/grdc/   (props changed)
 
 Modified: stable/8/games/grdc/grdc.c
 ==============================================================================
 --- stable/8/games/grdc/grdc.c	Fri Mar 12 00:25:04 2010	(r205055)
 +++ stable/8/games/grdc/grdc.c	Fri Mar 12 00:51:13 2010	(r205056)
 @@ -59,6 +59,7 @@ main(argc, argv)
  int argc;
  char **argv;
  {
 +struct timespec ts;
  long t, a;
  int i, j, s, k;
  int n;
 @@ -136,9 +137,9 @@ int t12;
  
  		attrset(COLOR_PAIR(2));
  	}
 +	time(&now);
  	do {
  		mask = 0;
 -		time(&now);
  		tm = localtime(&now);
  		set(tm->tm_sec%10, 0);
  		set(tm->tm_sec/10, 4);
 @@ -193,7 +194,19 @@ int t12;
  		}
  		movto(6, 0);
  		refresh();
 -		sleep(1);
 +		clock_gettime(CLOCK_REALTIME_FAST, &ts);
 +		if (ts.tv_sec == now) {
 +			if (ts.tv_nsec > 0) {
 +				ts.tv_sec = 0;
 +				ts.tv_nsec = 1000000000 - ts.tv_nsec;
 +			} else {
 +				ts.tv_sec = 1;
 +				ts.tv_nsec = 0;
 +			}
 +			nanosleep(&ts, NULL);
 +			now = ts.tv_sec + 1;
 +		} else
 +			now = ts.tv_sec;
  		if (sigtermed) {
  			standend();
  			clear();
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/120813: commit references a PR
Date: Fri, 12 Mar 2010 00:53:02 +0000 (UTC)

 Author: delphij
 Date: Fri Mar 12 00:51:25 2010
 New Revision: 205057
 URL: http://svn.freebsd.org/changeset/base/205057
 
 Log:
   MFC r203760: Improve time precision for grdc(6):
   
   Traditionally, grdc would obtain time through time(3) which in turn gets
   only the second part of clock (CLOCK_SECOND), and sleep for 1 second after
   each screen refresh.
   
   This approach would have two problems.  First, we are not guaranteed to
   be waken up at the beginning of a whole second, which will typically
   exhibit as a "lag" on second number.  Second, because we sleep for whole
   second, and the refresh process would take some time, the error would
   accumulate from time to time, making the lag variable.
   
   Make grdc(6) to use time(3) to get time only at the beginning, and sample
   time in CLOCK_REALTIME_FAST granularity after refreshing, and use the
   nanosecond part to caculate how much time we want to sleep.
   
   PR:		bin/120813
 
 Modified:
   stable/7/games/grdc/grdc.c
 Directory Properties:
   stable/7/games/grdc/   (props changed)
 
 Modified: stable/7/games/grdc/grdc.c
 ==============================================================================
 --- stable/7/games/grdc/grdc.c	Fri Mar 12 00:51:13 2010	(r205056)
 +++ stable/7/games/grdc/grdc.c	Fri Mar 12 00:51:25 2010	(r205057)
 @@ -59,6 +59,7 @@ main(argc, argv)
  int argc;
  char **argv;
  {
 +struct timespec ts;
  long t, a;
  int i, j, s, k;
  int n;
 @@ -136,9 +137,9 @@ int t12;
  
  		attrset(COLOR_PAIR(2));
  	}
 +	time(&now);
  	do {
  		mask = 0;
 -		time(&now);
  		tm = localtime(&now);
  		set(tm->tm_sec%10, 0);
  		set(tm->tm_sec/10, 4);
 @@ -193,7 +194,19 @@ int t12;
  		}
  		movto(6, 0);
  		refresh();
 -		sleep(1);
 +		clock_gettime(CLOCK_REALTIME_FAST, &ts);
 +		if (ts.tv_sec == now) {
 +			if (ts.tv_nsec > 0) {
 +				ts.tv_sec = 0;
 +				ts.tv_nsec = 1000000000 - ts.tv_nsec;
 +			} else {
 +				ts.tv_sec = 1;
 +				ts.tv_nsec = 0;
 +			}
 +			nanosleep(&ts, NULL);
 +			now = ts.tv_sec + 1;
 +		} else
 +			now = ts.tv_sec;
  		if (sigtermed) {
  			standend();
  			clear();
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
