Subject: Re: bin/34011: systat vmstat ignores refresh-interval argument
To: None <jdc@NetBSD.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,>
From: Julian Coleman <jdc@coris.org.uk>
List: netbsd-bugs
Date: 07/24/2006 21:25:02
The following reply was made to PR bin/34011; it has been noted by GNATS.

From: Julian Coleman <jdc@coris.org.uk>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/34011: systat vmstat ignores refresh-interval argument
Date: Mon, 24 Jul 2006 22:21:10 +0100

 >  26 seconds is the boundary where trouble starts (updates more
 >  than once a second) Does 256 ring a bell here? The function
 >  used is "timeout(millisecs)" from curses. The manual mentions
 >  no restriction on the number of millisecs supported. The limit
 >  is likely to be around 25600 millisecs as 26000 seems to fail.
 >  A short look into  lib/libcurses/timeout.c  shows that it  is the
 >  VTIME parameter(char!) of the termios interface - thus the systat
 >  implementation will currently be able to sensibly sleep 1-25 secs.
 >  For the curious: Above that the sleep time wraps to <secs-26>.4 s
 >  for 26-51 secs then +0.8, +0.2, +0.6, +0.0. But that is not useful
 >  unless you want the fast updates :-)
 >  
 >  Looks either like a doc bug or some more SMOP to get it o match 
 >  users expectations.
 
 Thanks for pointing this out.  This is indeed the problem.  Checking on a
 Solaris machine with the attached test, the maximum timeout is ~25 seconds.
 The attached patches make any delay above 25500ms into 25.5s and also fix a
 bug where calling notimeout() after calling timeout() was broken.  However,
 this latter fix is not ideal, as we will call tcsetattr() every time we
 call getch().  I'll produce a proper fix shortly (hopefully later in the
 week).
 
 J
 
   - - 8< - - - - - - - - - - - - - Cut here - - - - - - - - - - - - - >8 - -
 #include <curses.h>
 #include <time.h>
 
 int
 main ()
 {
 	time_t st, et;
 
 	initscr();
 	printw("Start\n");
 	timeout(40000);
 	st = time(NULL);
 	getch();
 	et = time(NULL);
 	printw("End (%ld)\n", et - st);
 	timeout(-1);
 	getch();
 	endwin();
 	
 }
   - - 8< - - - - - - - - - - - - - Cut here - - - - - - - - - - - - - >8 - -
 diff -ur /usr/src/lib/libcurses/curses_input.3 ./curses_input.3
 --- /usr/src/lib/libcurses/curses_input.3	2004-12-16 16:41:43.000000000 +0000
 +++ ./curses_input.3	2006-07-24 22:03:12.000000000 +0100
 @@ -334,6 +334,9 @@
  will be returned.
  Note that for a positive number, the timeout is only accurate to the nearest
  tenth of a second.
 +Also, the maximum value of
 +.Fa delay
 +is 25500 milliseconds.
  The
  .Fn wtimeout
  function does the same as
 diff -ur /usr/src/lib/libcurses/getch.c ./getch.c
 --- /usr/src/lib/libcurses/getch.c	2006-03-19 08:21:32.000000000 +0000
 +++ ./getch.c	2006-07-24 21:38:34.000000000 +0100
 @@ -594,6 +594,9 @@
  
  	k = 0;		/* XXX gcc -Wuninitialized */
  
 +#ifdef DEBUG
 +	__CTRACE("inkey (%d, %d)\n", to, delay);
 +#endif
  	for (;;) {		/* loop until we get a complete key sequence */
  reread:
  		if (state == INKEY_NORM) {
 @@ -890,6 +893,10 @@
  		switch (win->delay)
  		{
  		case -1:
 +			if (__delay() == ERR) {
 +				__restore_termios();
 +				return ERR;
 +			}
  			break;
  		case 0:
  			if (__nodelay() == ERR) {
 diff -ur /usr/src/lib/libcurses/timeout.c ./timeout.c
 --- /usr/src/lib/libcurses/timeout.c	2000-04-24 15:09:44.000000000 +0100
 +++ ./timeout.c	2006-07-24 21:58:36.000000000 +0100
 @@ -71,7 +71,13 @@
  	else if (!delay)
  		win->delay = delay;
  	else {
 -		/* timeout granularity is ms but VTIME is 0.1s */
 -		win->delay = delay / 100;
 +		/*
 +		 * 1. VTIME is a char
 +		 * 2. timeout granularity is ms but VTIME is 0.1s
 +		 */
 +		if (delay > 25500)
 +			win->delay = 255;
 +		else
 +			win->delay = delay / 100;
  	}
  }
 diff -ur /usr/src/lib/libcurses/tty.c ./tty.c
 --- /usr/src/lib/libcurses/tty.c	2004-01-20 08:30:55.000000000 +0000
 +++ ./tty.c	2006-07-24 21:35:02.000000000 +0100
 @@ -286,6 +286,9 @@
  int
  __delay(void)
   {
 +#ifdef DEBUG
 +	__CTRACE("__delay()\n");
 +#endif
  	/* Check if we need to restart ... */
  	if (_cursesi_screen->endwin)
  		__restartwin();
 @@ -306,6 +309,9 @@
  int
  __nodelay(void)
  {
 +#ifdef DEBUG
 +	__CTRACE("__nodelay()\n");
 +#endif
  	/* Check if we need to restart ... */
  	if (_cursesi_screen->endwin)
  		__restartwin();
 @@ -356,6 +362,9 @@
  int
  __timeout(int delay)
  {
 +#ifdef DEBUG
 +	__CTRACE("__timeout()\n");
 +#endif
  	/* Check if we need to restart ... */
  	if (_cursesi_screen->endwin)
  		__restartwin();
 @@ -379,6 +388,9 @@
  int
  __notimeout(void)
  {
 +#ifdef DEBUG
 +	__CTRACE("__notimeout()\n");
 +#endif
  	/* Check if we need to restart ... */
  	if (_cursesi_screen->endwin)
  		__restartwin();
 
   - - 8< - - - - - - - - - - - - - Cut here - - - - - - - - - - - - - >8 - -
 -- 
   My other computer also runs NetBSD    /        Sailing at Newbiggin
         http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/