Bug #1941
closedtimer intervals incorrectly rounded to clock resolution
100%
Description
If one currently attempts to create (say) a 1,000 usec POSIX interval timer
on x86, the actual cyclic created will not have the specified interval
of 1,000,000 nanoseconds, but rather 1,000,005 nanoseconds. Lest this
difference seem small, the 5 ppm error amounts to 5 microseconds per second;
after a mere 200 seconds of operation of such a timer, timer execution will
be off by an entire interval (namely, a millisecond). This is entirely
busted, and violates the most basic tenet of POSIX interval timers: that
they fire at the rate of the specified interval. The defective code is
astonishingly deliberate; in timer_settime():
/* * From the man page: * Time values that are between two consecutive non-negative * integer multiples of the resolution of the specified timer * shall be rounded up to the larger multiple of the resolution. * We assume that the resolution of any clock is less than one second. */ if (it->it_backend->clk_clock_getres(&res) == 0 && res.tv_nsec > 1) { long rem; if ((rem = when.it_interval.tv_nsec % res.tv_nsec) != 0) { when.it_interval.tv_nsec += res.tv_nsec - rem; timespecfix(&when.it_interval); } if ((rem = when.it_value.tv_nsec % res.tv_nsec) != 0) { when.it_value.tv_nsec += res.tv_nsec - rem; timespecfix(&when.it_value); } }
Here is the relevant section of the man page for timer_settime():
Time values that are between two consecutive non-negative integer mul‐ tiples of the resolution of the specified timer will be rounded up to the larger multiple of the resolution. Quantization error will not cause the timer to expire earlier than the rounded time value.
These two sentences say absolutely nothing about changing the programmed
interval -- merely that the timer will not fire earlier than the specified
time. Indeed, changing the programmed interval brings the implementation
into direct contradiction of the defined semantics of it_interval:
The reload value of the timer is set to the value specified by the it_interval member of value. When a timer is armed with a non-zero it_interval, a periodic (or repetitive) timer is specified.
Note that there is nothing that this does not say that the "reload value
of the timer is set to the value specified by the it_interval member of
value, rounded up to the nearest value that is evenly divided by the clock
resolution."
It is unfortunate that our current facilities for arbitrary resolution
interval timers are being sullied by a misread of the standard (a misread
that might well extend to a standards "test" that is itself broken).
Fortunately, the fix here is simple: the code that modifies the time and
interval to be evenly divided by the clock resolution should simply be
ripped out.