From owner-freebsd-bugs Sun Dec 8 12:40: 6 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 842C537B401 for ; Sun, 8 Dec 2002 12:40:03 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2D6C343E4A for ; Sun, 8 Dec 2002 12:40:03 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id gB8Ke2x3082888 for ; Sun, 8 Dec 2002 12:40:02 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id gB8Ke2QJ082887; Sun, 8 Dec 2002 12:40:02 -0800 (PST) Date: Sun, 8 Dec 2002 12:40:02 -0800 (PST) Message-Id: <200212082040.gB8Ke2QJ082887@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Enache Adrian Subject: Re: kern/46036: inaccurate timeouts in select(),nanosleep() + fix Reply-To: Enache Adrian Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR kern/46036; it has been noted by GNATS. From: Enache Adrian 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 - 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