bin/155374: [patch] grdc(6) timing loop still broken
Andy Farkas
chuzzwassa at gmail.com
Tue Mar 8 12:40:09 UTC 2011
>Number: 155374
>Category: bin
>Synopsis: [patch] grdc(6) timing loop still broken
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Mar 08 12:40:09 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator: Andy Farkas
>Release: 8.2-STABLE
>Organization:
>Environment:
FreeBSD 8.2-STABLE #0: Mon Mar 7 07:46:31 EST 2011
>Description:
After adding a small delay loop to the scrolling code of grdc(6) I noticed
that it was not keeping time properly.
This patch adds a delay during scrolling so that you can actually see it,
and also corrects the timing calculations within the do() loop.
The scrolling bit is trivial, see my followup to bin/151663.
The main thrust of this patch is to finally fix the timing of the do() loop:
1/ at the start of the loop we get the current time (now).
2/ we diplay the time, which may take some time, especially if scrolling.
3/ after display we get the time again (delay).
4/ we then calculate the amount of time needed to wait until a whole second has passed (wait).
>How-To-Repeat:
Add a delay during scrolling and notice how the time is displayed wrong.
>Fix:
patch (including scrolling patch):
%%%
--- /usr/src/games/grdc/grdc.c 2010-08-28 13:04:04.000000000 +1000
+++ ./grdc.c 2011-03-08 22:04:00.000000000 +1000
@@ -26,7 +26,12 @@
#define XLENGTH 58
#define YDEPTH 7
-struct timespec now;
+/* now: current time we start the loop
+ delay: current time we finish displaying the time
+ wait: amount of time we wait until next now second
+ scrold: amount of time between scrolling
+*/
+struct timespec delay, now, wait, scrold;
struct tm *tm;
short disp[11] = {
@@ -54,8 +59,6 @@
int
main(int argc, char *argv[])
{
- struct timespec delay;
- time_t prev_sec;
long t, a;
int i, j, s, k;
int n;
@@ -69,6 +72,7 @@
switch (ch) {
case 's':
scrol = 1;
+ scrold.tv_nsec = 40000000;
break;
case 't':
t12 = 1;
@@ -138,9 +142,9 @@
attrset(COLOR_PAIR(2));
}
- clock_gettime(CLOCK_REALTIME_FAST, &now);
- prev_sec = now.tv_sec;
+
do {
+ clock_gettime(CLOCK_REALTIME_FAST, &now);
mask = 0;
tm = localtime(&now.tv_sec);
set(tm->tm_sec%10, 0);
@@ -191,25 +195,31 @@
}
if(!s) {
refresh();
+ nanosleep(&scrold, NULL);
}
}
}
movto(6, 0);
refresh();
- clock_gettime(CLOCK_REALTIME_FAST, &now);
- if (now.tv_sec == prev_sec) {
- if (delay.tv_nsec > 0) {
- delay.tv_sec = 0;
- delay.tv_nsec = 1000000000 - now.tv_nsec;
- } else {
- delay.tv_sec = 1;
- delay.tv_nsec = 0;
+
+ clock_gettime(CLOCK_REALTIME_FAST, &delay);
+
+ if (delay.tv_sec == now.tv_sec) {
+ wait.tv_nsec = 1000000000 - (delay.tv_nsec - now.tv_nsec);
+ --n;
+ }
+ else {
+ if (delay.tv_nsec < now.tv_nsec) {
+ wait.tv_nsec = now.tv_nsec - delay.tv_nsec;
+ n -= delay.tv_sec - now.tv_sec;
+ }
+ else {
+ wait.tv_nsec = (1000000000 - delay.tv_nsec) + now.tv_nsec;
+ n -= (delay.tv_sec - now.tv_sec) + 1;
}
- nanosleep(&delay, NULL);
- clock_gettime(CLOCK_REALTIME_FAST, &now);
}
- n -= now.tv_sec - prev_sec;
- prev_sec = now.tv_sec;
+ nanosleep(&wait, NULL);
+
if (sigtermed) {
standend();
clear();
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list