Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

positive or negative tv_usec for adjtime with negative delta?

448 views
Skip to first unread message

Winston

unread,
Dec 5, 2016, 11:46:42 AM12/5/16
to
How are negative time amounts supposed to be represented in struct
timeval tv_usec for calls to adjtime(2)? The man pages, #include files,
and the web pages turned up by my Google searches aren't clear to me.

E.g., suppose I wish to adjtime by -7.25 seconds.

Possibility 1: tv_sec = -7; tv_usec = -250000;

Possibility 2: tv_sec = -8; tv_usec = +750000;

Experimental results with adjtime suggest something curious: Repeated
calls with, say, -7 -.25 seem to slow time by more than repeated calls
with -7 -.50.

I tried timeradd() and timersub() to see what they do:

timeradd() adds by pieces but doesn't canonicalize its results, and thus
is happy to return tv_usec < 0.

timersub(0, 4.50, result) returned -5 + .50, which suggests that's the
way the system wants negative values to be represented. timespecsub()
looks similar.

Anyone know what adjtime() actually wants for tv_usec for negative
adjustment values? [If there's a preferred representation, it'd be nice
if a comment describing it could be added somewhere such as
"/usr/include/sys/_timeval.h".]

TIA,
-WBE

Lowell Gilbert

unread,
Dec 5, 2016, 1:35:15 PM12/5/16
to
Winston <w...@UBEBLOCK.psr.com.invalid> writes:

> How are negative time amounts supposed to be represented in struct
> timeval tv_usec for calls to adjtime(2)? The man pages, #include files,
> and the web pages turned up by my Google searches aren't clear to me.

Um, yeah, everybody just uses the POSIX manal pages, which are rather
minimal. Part of the problem is that adjtime() exists primarily to be
used by NTP, and normally the interface to it is to use an ntpd. You
could refer to the NTP specification (RFC 5905, although the older
versions, notable RFC 1305, explain adjtime in more detail, although
note that some of those additional details are obsolete).

Also, what adjtime() does internally depends on a lot of parameters,
many of which aren't visible outside of the kernel. Again, see RFC5905.

> E.g., suppose I wish to adjtime by -7.25 seconds.
>
> Possibility 1: tv_sec = -7; tv_usec = -250000;
>
> Possibility 2: tv_sec = -8; tv_usec = +750000;
>
> Experimental results with adjtime suggest something curious: Repeated
> calls with, say, -7 -.25 seem to slow time by more than repeated calls
> with -7 -.50.

Repeated calls? How often? What kind of timing discipline are you using?

> I tried timeradd() and timersub() to see what they do:
>
> timeradd() adds by pieces but doesn't canonicalize its results, and thus
> is happy to return tv_usec < 0.
>
> timersub(0, 4.50, result) returned -5 + .50, which suggests that's the
> way the system wants negative values to be represented. timespecsub()
> looks similar.
>
> Anyone know what adjtime() actually wants for tv_usec for negative
> adjustment values? [If there's a preferred representation, it'd be nice
> if a comment describing it could be added somewhere such as
> "/usr/include/sys/_timeval.h".]

It seems to do a lot of conversions of its own, so I don't think that
matters, really.

What are you trying to do, anyway? It might help if you explain that.
For one thing, seven or eight seconds is a large change to slew; it
wouldn't complete for days.

--
Lowell Gilbert, embedded/networking software engineer
http://be-well.ilk.org/~lowell/

Winston

unread,
Dec 5, 2016, 3:20:12 PM12/5/16
to
I previously posted:
>> How are negative time amounts supposed to be represented in struct
>> timeval tv_usec for calls to adjtime(2)? The man pages, #include files,
>> and the web pages turned up by my Google searches aren't clear to me.

Lowell Gilbert <lgus...@be-well.ilk.org> kindly replied:
> Um, yeah, everybody just uses the POSIX manal pages, which are rather
> minimal. Part of the problem is that adjtime() exists primarily to be
> used by NTP, and normally the interface to it is to use an ntpd.

Solaris/SunOS used to have "date -a S.s", but, yes, FreeBSD's date
doesn't.

> Also, what adjtime() does internally depends on a lot of parameters,
> many of which aren't visible outside of the kernel. Again, see RFC5905.

>> Experimental results with adjtime suggest something curious: Repeated
>> calls with, say, -7 -.25 seem to slow time by more than repeated calls
>> with -7 -.50.

> Repeated calls? How often? What kind of timing discipline are you using?

Once a day or less for many days; not rapidly (where the previous call
might not yet have completed and adjtime() reports an amount not yet
adjusted). I check the adjtime return value to ensure that there was no
adjustment not yet finished.

>> Anyone know what adjtime() actually wants for tv_usec for negative
>> adjustment values?

> It seems to do a lot of conversions of its own, so I don't think that
> matters, really.

If adjtime or any other system call has a preference for how negative
times should be specified, it'd be nice to say which format it/they
prefer, in the man page or at least in <sys/_timeval.h>.

> What are you trying to do, anyway?

Compare computer clock speed against wall clock time over many months
and adjust the clock manually (via periodic calls) rather than use ntpd.
(E.g., for a stand-alone system.)

> For one thing, seven or eight seconds is a large change to slew; it
> wouldn't complete for days.

That's not what I've seen with FreeBSD 8, 9, 10, or 11. Adjustments of
even 40-50 seconds have happened in a few hours.

I just ran a test, checking occasionally:
14:21: I did adjtime of -8.0 seconds.
14:48: it had corrected about -7 seconds.
14:53: the adjustment looked complete.
Elapsed time: about 32 minutes, so ~1/4 second per minute.
-WBE

Christian Weisgerber

unread,
Dec 5, 2016, 5:30:08 PM12/5/16
to
On 2016-12-05, Winston <w...@UBEBLOCK.psr.com.invalid> wrote:

> How are negative time amounts supposed to be represented in struct
> timeval tv_usec for calls to adjtime(2)? The man pages, #include files,
> and the web pages turned up by my Google searches aren't clear to me.

From kern_adjtime() in /sys/kern/kern_ntptime.c:

time_adjtime = (int64_t)delta->tv_sec * 1000000 +
delta->tv_usec;

time_adjtime is then used to perform the actual correction in
ntp_update_second().

--
Christian "naddy" Weisgerber na...@mips.inka.de

Winston

unread,
Dec 5, 2016, 6:41:20 PM12/5/16
to
I previously asked:
>> How are negative time amounts supposed to be represented in struct
>> timeval tv_usec for calls to adjtime(2)? The man pages, #include files,
>> and the web pages turned up by my Google searches aren't clear to me.

Christian Weisgerber <na...@mips.inka.de> kindly replied:
> From kern_adjtime() in /sys/kern/kern_ntptime.c:
>
> time_adjtime = (int64_t)delta->tv_sec * 1000000 +
> delta->tv_usec;
>
> time_adjtime is then used to perform the actual correction in
> ntp_update_second().

So as long as tv_usec is signed, it indeed doesn't matter whether one
passes -7 -.25 or -8 +.75, but the latter would work even if tv_usec
were unsigned.

OK. Thanks!
-WBE

Christian Weisgerber

unread,
Dec 6, 2016, 11:30:06 AM12/6/16
to
On 2016-12-05, Winston <w...@UBEBLOCK.psr.com.invalid> wrote:

>> Um, yeah, everybody just uses the POSIX manal pages, which are rather
>> minimal. Part of the problem is that adjtime() exists primarily to be
>> used by NTP, and normally the interface to it is to use an ntpd.
>
> Solaris/SunOS used to have "date -a S.s", but, yes, FreeBSD's date
> doesn't.

SunOS also had "rdate -a", a reimplementation of which is available
as a port on FreeBSD. Yet another adjtime() user is timed(8).

Since 1993, the preferred kernel interface for David Mills' ntpd
reference implementation has been ntp_adjtime(2) aka adjtimex(2).
Only if this doesn't exist will ntpd fall back to adjtime().

>> For one thing, seven or eight seconds is a large change to slew; it
>> wouldn't complete for days.
>
> That's not what I've seen with FreeBSD 8, 9, 10, or 11. Adjustments of
> even 40-50 seconds have happened in a few hours.

The maximum slew rate for adjtime() is 5 ms/s (5000 ppm).

Winston

unread,
Dec 6, 2016, 2:02:21 PM12/6/16
to
Lowell Gilbert <lgus...@be-well.ilk.org> had previously replied:
>>> For one thing, seven or eight seconds is a large change to slew; it
>>> wouldn't complete for days.

to which I replied:
>> That's not what I've seen with FreeBSD 8, 9, 10, or 11. Adjustments
>> of even 40-50 seconds have happened in a few hours.

Then Christian Weisgerber <na...@mips.inka.de> provided the more
accurate answer:
> The maximum slew rate for adjtime() is 5 ms/s (5000 ppm).

So it's 200:1, or 3 1/3 minutes/second. That's:
* just under half an hour for an 8 second change,
* 2.5 hours for a 45 second change,
* 3h20m for a 60 second change,

and right in line with what I've observed. Thanks!
-WBE
0 new messages