From owner-cvs-src@FreeBSD.ORG Thu Oct 20 11:50:36 2005 Return-Path: X-Original-To: cvs-src@FreeBSD.org Delivered-To: cvs-src@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D86F616A41F; Thu, 20 Oct 2005 11:50:35 +0000 (GMT) (envelope-from bde@zeta.org.au) Received: from mailout1.pacific.net.au (mailout1.pacific.net.au [61.8.0.84]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2E75D43D5A; Thu, 20 Oct 2005 11:50:34 +0000 (GMT) (envelope-from bde@zeta.org.au) Received: from mailproxy2.pacific.net.au (mailproxy2.pacific.net.au [61.8.0.87]) by mailout1.pacific.net.au (8.13.4/8.13.4/Debian-3) with ESMTP id j9KBoXuN022831; Thu, 20 Oct 2005 21:50:33 +1000 Received: from katana.zip.com.au (katana.zip.com.au [61.8.7.246]) by mailproxy2.pacific.net.au (8.13.4/8.13.4/Debian-3) with ESMTP id j9KBoUrw024906; Thu, 20 Oct 2005 21:50:32 +1000 Date: Thu, 20 Oct 2005 21:50:31 +1000 (EST) From: Bruce Evans X-X-Sender: bde@delplex.bde.org To: Poul-Henning Kamp In-Reply-To: <8229.1129790637@critter.freebsd.dk> Message-ID: <20051020211131.A874@delplex.bde.org> References: <8229.1129790637@critter.freebsd.dk> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed Cc: cvs-src@FreeBSD.org, src-committers@FreeBSD.org, Andre Oppermann , cvs-all@FreeBSD.org Subject: Re: cvs commit: src/usr.bin/vmstat vmstat.c src/usr.bin/w w.c X-BeenThere: cvs-src@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: CVS commit messages for the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Oct 2005 11:50:36 -0000 On Thu, 20 Oct 2005, Poul-Henning Kamp wrote: > In message <20051020131450.T99502@delplex.bde.org>, Bruce Evans writes: >> On Tue, 18 Oct 2005, Poul-Henning Kamp wrote: > >> Using CLOCK_MONOTONIC doesn't work because it it gives the system's idea >> of the time and doesn't try hard to keep in sync with the real time. >> In particular, it doesn't jump when the real time is stepped by >> settimeofday(2) or clock_settime(2). > > Uhm, Bruce, > > That is the exact reason why we have CLOCK_MONOTONIC: it doesn't jump. I know why we have it and what it does. > With respect to leapseconds: Whoever was responsible for POSIX's > decision should be forced to work as quality assurance inspector > in a factory which makes cuu-cuu clocks for the rest of their lives. POSIX's specification of CLOCK_MONOTONIC seems to be missing leap seconds problems. It seems to be required to actually work; thus it should give the difference in real time, in seconds with nanoseconds resolution, relative to its starting point, so it must include leap seconds. Of course it can't reasonably be expected to have nanoseconds accuracy. Since it cannot jump, it also cannot reasonably be expected to have even seconds accuracy all the time. There will be times just after the time is synced with an external accurate clock when the real time is kown very accurately but the monotonic time is known (at the kernel level) to be very innaccurate (since the monotonic time cannot jump to match the real time, especially backwards). However, it is reasonable to expect that the monotonic time is slewed to correct this difference. This is not done in FreeBSD. difftime() also seems to be required to actually work. According to draft C99 (n869.txt): % [#2] The difftime function computes the difference between % two calendar times: time1 - time0. time_t's cannot be naively subtracted in general in C, so the difference here must be formal. The difference is required to contain leap seconds by POLA. According to draft POSIX.1-2001 (d7.txt): % 8275 CX The functionality described on this reference page is aligned with the ISO C standard. Any % 8276 conflict between the requirements described here and the ISO C standard is unintentional. This % 8277 volume of IEEE Std 1003.1-200x defers to the ISO C standard. % 8278 The difftime( ) function shall compute the difference between two calendar times (as returned by % 8279 time( )): time1- time0. Here naive subtraction gives a result, but it cannot always give the correct result since time_t's don't contain leap seconds in POSIX. Since C99 has precedence, difftime() cannot be implemented using naive subtraction; it must somehow adjust for leap seconds being missing from the time_t's. Back to the utilities: according to the standards, it seems to be equally correct to implement "double uptime()" as: /* Done in kernel; happens to give 0 in FreeBSD implementation: */ clock_gettime(CLOCK_MONOTONIC, &boottime); clock_gettime(CLOCK_MONOTONIC, &now); return (now.tv_sec - boottime.tv_sec + 1e-9 * (now.tv_nsec - boottime.tv_nsec); and as: /* Done in kernel; nonzero except if you booted in 1970: */ clock_gettime(CLOCK_REALTIME, &boottime); clock_gettime(CLOCK_REALTIME, &now); /* Restore leap seconds if necessary; lose nanoseconds resolution: */ return difftime(now.tv_sec, boottime.tv_sec); Different bugs prevent both of these working as well as they should. For w, no one should even notice the inaccuracies of a few seconds caused by the bugs. For vmstat, the first method works better because the bugs in the monotonic clock cause only small relative errors in the difference, while for the second method only the bugs can be fixed -- large relative errors in the difference caused by stepping the clock are unfixable. Bruce