M. Warner Losh wrote:
>                                 But ntp_gettime returns a timespec
>for the time, as well as a time_state for the current time status,
>which includes TIME_INS and TIME_DEL for psotive and negative leap
>second 'warning' for end of the day so you know there will be a leap
>today, and TIME_WAIT for the actual positive leap second itself
>(there's nothing for a negative leapsecond, obviously).

Actually the interface is more complicated than that.  TIME_WAIT indicates
that a leap second recently occurred, and continues to be returned
until the command bit that initiated the leap second has been cleared.
The status during a leap second is meant to be TIME_OOP.  TIME_OK is the
normal state.  If the clock is not properly synchronised then TIME_ERROR
(a.k.a. "TIME_ERR" or "TIME_BAD") is returned instead of the leap state:
the leap second engine still operates in this situation (at least it
does on Linux), but you don't get to see the state variable.

Mills's paper "A Kernel Model for Precision Timekeeping"
<ftp://ftp.udel.edu/pub/people/mills/memos/memo96b.ps> says that the
time_t should repeat the last second of the day.  That would give you
these behaviours:

        398 TIME_DEL     398 TIME_OK      398 TIME_INS
        400 TIME_WAIT    399 TIME_OK      399 TIME_INS
        401 TIME_WAIT    400 TIME_OK      399 TIME_OOP
        402 TIME_WAIT    401 TIME_OK      400 TIME_WAIT

Actually, though, the paper doesn't require the state change to be
atomic with the change of time_t.  It's allowed to be slightly delayed.
(It is in fact delayed a few milliseconds on Linux.)  So what is actually
seen is this:

        398.5 TIME_DEL     398.5 TIME_OK      398.5 TIME_INS
        399.0 TIME_DEL     399.0 TIME_OK      399.0 TIME_INS
        400.5 TIME_WAIT    399.5 TIME_OK      399.5 TIME_INS
        401.0 TIME_WAIT    400.0 TIME_OK      400.0 TIME_INS
        401.5 TIME_WAIT    400.5 TIME_OK      399.5 TIME_OOP
        402.0 TIME_WAIT    401.0 TIME_OK      400.0 TIME_OOP
        402.5 TIME_WAIT    401.5 TIME_OK      400.5 TIME_WAIT

There is enough information in there to fully decode it, but it means
looking at more states than would be required in the nominal version.
For example, if you see TIME_INS with a time that appears to be just
after midnight, then you're actually inside a positive leap second.
The second that time_t repeats is neither the second before midnight
[399, 400] nor the second after midnight [400, 401], but something
between those, encompassing midnight, approximately [399.005, 400.005].

Interestingly, once you've got all the decode logic required to handle
this, it's also possible to handle a system where time_t repeats the
first second of the next day.  This system wouldn't use the TIME_OOP
state at all, using TIME_INS to indicate the leap second.  It's just
the extreme end of where the repeated second could be placed.

I think this is a horrible mess and all the leap second adjustments should
happen in user space.  (Filesystems that use UTC-based timestamps would
require the kernel to be able to translate too, but this shouldn't affect
the clock or the APIs.)  NTP has problems because the leap second handling
was grafted on and it has no memory of leap seconds.  Synchronisation
and kernel APIs should use a plain linear count of TAI seconds, because
they're not concerned with time-of-day per se.  Anything that does care
about time-of-day can do the conversion itself, just like anything that
cares about day-of-week or day-of-year.  UTC is a calendar.


Reply via email to