Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Oct 2005 22:38:30 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        "M. Warner Losh" <imp@bsdimp.com>
Cc:        cvs-src@FreeBSD.org, phk@phk.freebsd.dk, src-committers@FreeBSD.org, andre@FreeBSD.org, cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/usr.bin/vmstat vmstat.c src/usr.bin/w w.c 
Message-ID:  <20051021210822.E4739@delplex.bde.org>
In-Reply-To: <20051020.121318.117917917.imp@bsdimp.com>
References:  <25112.1129812291@critter.freebsd.dk> <20051021011035.T1945@delplex.bde.org> <20051020.121318.117917917.imp@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 20 Oct 2005, M. Warner Losh wrote:

> In message: <20051021011035.T1945@delplex.bde.org>
>            Bruce Evans <bde@zeta.org.au> writes:
> : > You can by definition not implment difftime correctly since the
> : > time_t timescale does not contain any indication of leapseconds.
> : >
> : > This means that there is no way to tell which side of an inserted
> : > leapsecond a time(2) timestamp comes from:
> : >
> : > 	UTC		time(2)
> : > 	23:59:57	N-3
> : > 	23:59:58	N-2
> : > 	23:59:59	N-1
> : > 	23:59:60	N
> : > 	00:00:00	N
> : > 	00:00:01	N+1
> : >
> : > Worst case, difftime() will be wrong by two seconds: taking the difference
> : > from one leapsecond to another and guessing wrong in both ends.
> :
> : It only has to be wrong by 1 or 2 seconds for short intervals when a leap
> : seconds occurs.  Not adjusting makes difftime() wrong across all intervals
> : containing a leap second, with an error of the number of leap seconds in
> : the interval (+- 1 or 2 for leap seconds at endpoints).
>
> Where do you keep the table of leapseconds?  How do you make sure it
> gets updated?  As far as I know, there's no installed leap second data
> on the system, unless you've enabled the 'run in TAI instead of UTC'
> mode.

At the source level, the table is in /usr/src/share/zoneinfo/leapseconds.
This file was updated in revs.1.[13-14] (2005/07/05-2005/08/26) to add the
leap second at the end of this year.  Before that, the file hasn't needed
to change since the previous leap second in 1998, but has some cosmetic
changes.

Complain to wollman if this file is not updated. :-)

At runtime, _a_ table is in /etc/localtime.  According to tzfile(5):

% DESCRIPTION
%      The time zone information files used by tzset(3) begin with the magic
%      characters ``TZif'' to identify them as time zone information files, fol-
%      lowed by sixteen bytes reserved for future use, followed by four four-
%      byte values written in a ``standard'' byte order (the high-order byte of
%      the value is written first).  These values are, in order:
% ...
%      tzh_leapcnt     The number of leap seconds for which data is stored in
%                      the file.
% ...
%      Then there are tzh_leapcnt pairs of four-byte values, written in standard
%      byte order; the first value of each pair gives the time (as returned by
%      time(3)) at which a leap second occurs; the second gives the total number
%      of leap seconds to be applied after the given time.  The pairs of values
%      are sorted in ascending order by time.

Unfortunately, a null table is used by default since LEAPSECONDS is
not defined (see zoneinfo/Makefile).  This dates from FreeBSD-2.  In
zoneinfo/Makefile before 1.6 and in FreeBSD-1, instead of LEAPSECONDS
there were targets posix_only, right_only, posix_right and right_posix
to support various amounts of POSIX time_t mistakes.  FreeBSD-1.1.5
used posix_right, which gave "both sets of data available, with leap
seconds not counted normally".  I think this means FreeBSD-1.1.5 used
full POSIX time_t mistakes but put the leapseconds database in binaries
for abnormal use (whatever that is; I guess it is controlled by a
runtime switch).  FreeBSD_1.0 used right_posix, which gave right
behaviour normally and POSIX mistakes abnormally.  This was found to
be to abnormal to be the default, so FreeBSD switched to posix_right.
Then in rev.1.6 before FreeBSD_2.0, the right/posix stuff was replaced by
the LEAPSECONDS knob and the knob was for some reason turned around
so the behaviour changed from posix_right to plain posix[_wrong].
There was also a change from right_only to posix_right in rev.1.5.

> Leaving aside the leap table issue for the moment, there's a more
> fundamental problem.  You cannot possibly compute correct answers for
> times that are in the future, even a little ways in the future.  What
> if time1 is June 30, 2006 23:59:58 and time2 is July 1, 2006 00:00:01.
> While neither of these seconds are ambiguous, no one on the planet can
> say today, with certainty, what the answer will be.  We have to wait
> until early January when IERS issues the next Bulletin C.  You cannot
> know today if the right answer is 2, 3 or 4.  If there's a negative
> leap second at the end of June 30, then the answer is 2, if there's no
> leap second the answer is 3, if there is a positive leap second, the
> answer is 4.  One can only predict what might happen.  Until 6 months
> before the leap second, no one knows what the schedule will be.

This is not a problem for times returned by clock_gettime(), since those
times are in the past.

64-bit time_t's and/or ints also permit asking the time library to do
impossible predictions.

Bruce



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