Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 03 Dec 2020 21:00:23 +0000
From:      "Poul-Henning Kamp" <phk@phk.freebsd.dk>
To:        Ian Lepore <ian@freebsd.org>
Cc:        Cy Schubert <Cy.Schubert@cschubert.com>, freebsd-arch@freebsd.org
Subject:   Re: struct timex and Linux adjtimex()
Message-ID:  <25487.1607029223@critter.freebsd.dk>
In-Reply-To: <5e0db735b29f1ece02521871b2cd392c3467101d.camel@freebsd.org>
References:  <202012030523.0B35NsG7003810@slippy.cwsent.com> <4086.1606982335@critter.freebsd.dk> <5e0db735b29f1ece02521871b2cd392c3467101d.camel@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--------
Ian Lepore writes:
> On Thu, 2020-12-03 at 07:58 +0000, Poul-Henning Kamp wrote:

> We run freebsd on hardware whose timecounter clock is fed from a gps-
> disciplined oscillator and the hardware in the SOC implementing that
> clock can capture the counter on an edge of an incoming PPS (which is
> generated from the same disciplined oscillator), so we can get fairly
> accurate phase measurements. 
>
> But I can't set the time with anything like the same accuracy.

Wrong.

You can set time with nanosecond precision, even pretty quickly,
but you cannot *step* it with nano-second precision.

(This last is an universal truth:  The code to do the load+add+store
takes instructions on the order of several nanoseconds, and try as
you might, you cannot calibrate that offset to sub-nanosecond
uncertainty on contemporary hardware.  This is why there is no
escaping fiddling with minute frequency adjustments and measurements
over a period of time, if you want your clock to be precise at the
~sub-20 nanosecond level.)

MOD_OFFSET will precisly slew the clock a given offset over a period
of time, in an exponential-decay manner, taking pains to ensure
time never stops og goes backwards.

The "no-step-no-stop" policy was a very deliberate design decision
by Dave Mills, and not one he was ever willing to compromise on.

His argument was that while forward steps are generally not too
troublesome, time should never *ever* go backwards, *and* that
postive and negative offsets should be handled identically.

On a purely philosophical basis, that argument is unassailable,
but we have all tried CMOS RTC's giving us bogus time.

Both the "initial step" code in ntpd(8) and the ntpdate(8) program
exists as workarounds around Daves veto, to cope with bad CMOS
time.

Fortunately time-steps are a lot less poisonous these days, because
people have discovered CLOCK_MONOTONIC, but "no-step-no-stop" is
fundamentally still the right way to go.

Anyway, the "ADJ_SETOFFSET" is a hackish bolt-on, starting with the
fact that the "ADJ_" prefix is totally out of family for <sys/timex.h>,
and any interaction with the rest of the PLL is unspecified.

That is why I'm not too entusiastic about adopting it.

A more correct integration in the kernel-pll would be to have a
modifier flag for MOD_OFFSET which indicates that a step is desired,
and document that it zeros the PLL as part of the operation.

But as mentioned above, no matter what, the precision is probably
limited to around 25 nanoseconds, possibly more depending on locking,
and while that may be good enough for your specific case, it is
a blemish on the otherwise very stringent about precision PLL code.


> I notice a struct timeval was mentioned, but hopefully that's in a
> context where MOD_NANO/STA_NANO apply and tv_usec will actually convey
> nanos?

Yes, when the _NANO flag is set, the timeval is a timespec

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe    
Never attribute to malice what can adequately be explained by incompetence.



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