Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Dec 2002 12:40:02 -0800 (PST)
From:      Enache Adrian <enache@rdslink.ro>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/46036: inaccurate timeouts in select(),nanosleep() + fix
Message-ID:  <200212082040.gB8Ke2QJ082887@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/46036; it has been noted by GNATS.

From: Enache Adrian <enache@rdslink.ro>
To: FreeBSD-gnats-submit@FreeBSD.ORG
Cc:  
Subject: Re: kern/46036: inaccurate timeouts in select(),nanosleep() + fix
Date: Sun, 8 Dec 2002 22:33:41 +0200

 On Sat, Dec 07, 2002 at 11:57:40PM +1100, Bruce Evans wrote:
 > tvtohz() actually adds 1 to ensure that the sleep time is at least the
 > specified time.  This gives a minimum sleep time of 0.0 ticks longer
 > than the specified sleep time (as required by standards) and a maximum
 > sleep time of about 1.0 tick longer than the specified sleep time,
 > with an average sleep time of about 0.5 ticks longer.  Not adding 1
 > would give a {min,max,avg} sleep time of about {-1.0,0.0,-0.5} ticks
 > longer than specified; i.e., it would be shorter than specified (broken)
 > in most cases.
 ...
 > and we are mostly in sync with clock interrupts.  In general the error
 > from not adding 1 is up to 1 tick (see above).
 The average sleep time seems to be with ~ 0.995 longer on an idle
 machine - much longer on a loaded one where ticks are lost.
 
 For the error to be down to -1 tick with an average of -0.5 ticks
 (when not adding 1) the tick value must be very small - this doesn't
 seem to happen with the standard 100hz. Under high load the error
 tends to be positive.
 
 When the user has asked for something not multiple of tick the
 value will be correctly rounded up by tvtohz() and the error will
 be positive too.
 
 > I thought that Linux gets timeouts right -- at least sleep() used to
 > work except in very early versions of Linux-0.x.  Perhaps it uses
 > clock interrupts to get to get close to the timeout and then
 > udelay() to get closer if the residual timeout is small.  In general,
 > the residual could be up to `tick' usec, but in cases that are in sync
 > with the clock like your test program, the residual would be small
 > (about 44 usec) and udelay() could reasonably handle it.
 Oh no.
 Linux doesn't seem to call udelay() to handle the residual timeout.
 
 Only nanosleep() works like in FreeBSD ( one tick longer by just
 adding one - this is why many recommend to use select() instead
 of usleep() ...)
 
 from kernel/timer.c
 	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
 
 The silly test program, when run - with some minor modifications
 -----------------------
 +#include <sys/param.h>
 -       struct clockinfo clock;
 -       mib[0] = CTL_KERN; mib[1] = KERN_CLOCKRATE;
 -       k = sizeof clock;
 -       if (sysctl(mib,2,&clock,&k,NULL,0)) err(1,"sysctl");
 -       savtv.tv_usec -= savtv.tv_usec % clock.tick;
 +       savtv.tv_usec -= savtv.tv_usec % (1000000 / HZ);
 _______________________
 on linux 2.4.18 says:
 -   0 s        171 us
 -   0 s        181 us
 -   0 s        184 us
 
         --input
 -   0 s        169 us
 -   0 s        180 us
 
 According to you it is broken to sleep less than specified.
 
 Does it exist a standard specification for this case ?
 A quick browsing through susv3 shows that only nanosleep()
 is required to do so:
 functions/select.html:
 	"If the timeout parameter is not a  null pointer,
 	 it specifies a maximum interval to wait for the
           selection to complete."
 functions/nanosleep.html
 	"But, except for the case of being interrupted by
 	a signal, the suspension time shall not be less than
 	the time specified by rqtp, as measured by the
 	system clock CLOCK_REALTIME"
 
 but I'll keep reading on ...
 
 thank you & best regards
 Adi
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212082040.gB8Ke2QJ082887>