From: Alexander Gordeev <lasaine@lvk.cs.msu.su>
To: john stultz <johnstul@us.ibm.com>
Cc: linux-kernel@vger.kernel.org, linuxpps@ml.enneenne.com,
"Nikita V. Youshchenko" <yoush@cs.msu.su>,
stas@lvk.cs.msu.su, Rodolfo Giometti <giometti@enneenne.com>,
Rodolfo Giometti <giometti@linux.it>,
Andrew Morton <akpm@linux-foundation.org>,
Alan Cox <alan@lxorguk.ukuu.org.uk>, Ingo Molnar <mingo@elte.hu>,
Thomas Gleixner <tglx@linutronix.de>,
Rik van Riel <riel@redhat.com>
Subject: Re: [PATCH 1/5] ntp: add hardpps implementation
Date: Thu, 4 Feb 2010 02:51:53 +0300 [thread overview]
Message-ID: <20100204025153.52fe962a@lvk.cs.msu.su> (raw)
In-Reply-To: <1265234930.3255.54.camel@work-vm>
[-- Attachment #1: Type: text/plain, Size: 8878 bytes --]
Thanks for the review!
В Wed, 03 Feb 2010 14:08:50 -0800
john stultz <johnstul@us.ibm.com> пишет:
> On Wed, 2010-02-03 at 23:56 +0300, Alexander Gordeev wrote:
> > This commit adds hardpps() implementation based upon the original
> > one from the NTPv4 reference kernel code. However, it is highly
> > optimized towards very fast syncronization and maximum stickness to
> > PPS signal. The typical error is less then a microsecond.
> > To make it sync faster I had to throw away exponential phase filter
> > so that the full phase offset is corrected immediately. Then I also
> > had to throw away median phase filter because it gives a bigger
> > error itself if used without exponential filter.
> > Maybe we will find an appropriate filtering scheme in the future but
> > it's not necessary if the signal quality is ok.
> >
> > Signed-off-by: Alexander Gordeev <lasaine@lvk.cs.msu.su>
>
> Very cool! Bunch of style comments below.
>
> One other thing: From the comments in the code, it looks like this may
> have come straight from the reference implementation. You might want
> to provide some extra documentation or comment providing proper
> credit, and clarifying that the code is in fact GPLv2 compatible.
>
> Also please review Section 12 of Documentation/SubmittingPatches
Indeed, this code is a direct descendant of the reference
implementation. However it is mostly rewritten because the original
code was too hard to read. But I thought it is not an issue because the
whole ntp.c seems to have a lot of code from it... Well, I'm not quite
good in license compatibility. :)
Here is the copyright notice from the original code for reference:
/***********************************************************************
* *
* Copyright (c) David L. Mills 1993-2001 *
* *
* Permission to use, copy, modify, and distribute this software and *
* its documentation for any purpose and without fee is hereby *
* granted, provided that the above copyright notice appears in all *
* copies and that both the copyright notice and this permission *
* notice appear in supporting documentation, and that the name *
* University of Delaware not be used in advertising or publicity *
* pertaining to distribution of the software without specific, *
* written prior permission. The University of Delaware makes no *
* representations about the suitability this software for any *
* purpose. It is provided "as is" without express or implied *
* warranty. *
* *
**********************************************************************/
Maybe adding a comment like the one above second_overflow() is enough?
> [snip]
> > +long pps_tf[3]; /* phase median filter */
> > +s64 pps_freq; /* scaled frequency offset
> > (ns/s) */ +s64 pps_fcount; /* frequency
> > accumulator */ +long pps_jitter; /* nominal jitter
> > (ns) */ +long pps_stabil; /* nominal stability
> > (scaled ns/s) */ +int pps_valid; /* signal
> > watchdog counter */ +int pps_shift; /*
> > nominal interval duration (s) (shift) */ +int
> > pps_shiftmax; /* max interval duration (s) (shift)
> > */ +int pps_intcnt; /* interval counter */ +
> > +/*
> > + * PPS signal quality monitors
> > + */
> > +long pps_calcnt; /* calibration intervals */
> > +long pps_jitcnt; /* jitter limit exceeded */
> > +long pps_stbcnt; /* stability limit exceeded */
> > +long pps_errcnt; /* calibration errors */
> > +
>
> Shouldn't all of the above values be made static?
Sure, thanks.
> [snip]
>
> > /*
> > @@ -233,8 +277,6 @@ static enum hrtimer_restart
> > ntp_leap_second(struct hrtimer *timer) */
> > void second_overflow(void)
> > {
> > - s64 delta;
> > -
> > /* Bump the maxerror field */
> > time_maxerror += MAXFREQ / NSEC_PER_USEC;
> > if (time_maxerror > NTP_PHASE_LIMIT) {
> > @@ -248,9 +290,27 @@ void second_overflow(void)
> > */
> > tick_length = tick_length_base;
> >
> > - delta = shift_right(time_offset, SHIFT_PLL
> > + time_constant);
> > - time_offset -= delta;
> > - tick_length += delta;
> > +#ifdef CONFIG_NTP_PPS
> > + if (time_status & STA_PPSTIME && time_status &
> > STA_PPSSIGNAL) {
> > + tick_length += time_offset;
> > + time_offset = 0;
> > + } else
> > +#endif /* CONFIG_NTP_PPS */
> > + {
> > + s64 delta;
> > + delta =
> > + shift_right(time_offset, SHIFT_PLL +
> > time_constant);
> > + time_offset -= delta;
> > + tick_length += delta;
> > + }
>
>
> Ugh. Surely there's a better way to do this then using the ifdefs in
> code?
>
> Maybe something like:
>
> #ifdef CONFIG_NTP_PPS
> /* Comment about how pps consumes the whole offset */
> static inline s64 ntp_offset_chunk(s64 offset)
> {
> if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL)
> return offset
> else
> return shift_right(offset, SHIFT_PLL + time_constant);
> }
> #else
> static inline s64 ntp_offset_chunk(s64 offset)
> {
> return shift_right(offset, SHIFT_PLL + time_constant);
> }
> #endif
>
> Then in second_overflow():
>
> delta = ntp_offset_chunk(time_offset);
> time_offset -= delta;
> tick_length += delta;
>
> Feel free to use a better name then ntp_offset_chunk(), but this keeps
> the logic from being obfuscated by all the #ifdefs
>
> > +#ifdef CONFIG_NTP_PPS
> > + if (pps_valid > 0)
> > + pps_valid--;
> > + else
> > + time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
> > + STA_PPSWANDER | STA_PPSERROR);
> > +#endif /* CONFIG_NTP_PPS */
>
> Similarly, can some sort of pps_dec_valid() inline function be used
> here?
Ok, it is better indeed.
> [snip]
>
> > +#ifdef CONFIG_NTP_PPS
> > +
> > +/* normalize the timestamp so that nsec is in the
> > + ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval */
> > +static inline struct timespec pps_normalize_ts(struct timespec ts)
> > +{
> > + if (ts.tv_nsec > (NSEC_PER_SEC >> 1)) {
> > + ts.tv_nsec -= NSEC_PER_SEC;
> > + ts.tv_sec++;
> > + }
> > +
> > + return ts;
> > +}
>
> Hrmm.. So by converting a timespec into a second + [-NSEC_PER_SEC/2,
> NSEC_PER_SEC/2] value, you aren't really using a timespec anymore,
> right? I mean, the timepsec_valid() would fail in many cases, for
> instance.
>
> I realize its pretty close, and you *can* use a timespec this way, but
> to me it seems reasonable to introduce a new structure (pps_normtime?)
> so that its clear you shouldn't exchange timespec values and
> pps_normtime values directly?
>
> This is sort of a nit, and maybe others disagree, so not the most
> critical issue. But it seems like you're abusing the structure a bit.
Well, I don't mind adding a structure for this. Seems like timespec
is not expected to be used this way.
> [snip]
> > +/* decrease frequency calibration interval length */
> > +static inline void pps_dec_freq_interval(void)
> > +{
> > + if (--pps_intcnt <= -4) {
> > + pps_intcnt = -4;
>
> Is -4 a magic value?
>
> [snip]
> > + } else { /* good sample */
> > + if (++pps_intcnt >= 4) {
> > + pps_intcnt = 4;
>
> Again, the magic 4?
Yep :)
The values are from the reference implementation. Frequency calculation
is mostly the same as in the original code because it works good.
I'll add a define for these values.
> [snip]
> > + pps_stabil += (div_s64(((s64)delta_mod) <<
> > + (NTP_SCALE_SHIFT - SHIFT_USEC),
> > + NSEC_PER_USEC) - pps_stabil) >>
> > PPS_FAVG;
>
> Hmm. Two 64bit divides in this path? This code would run each second,
> right? It would probably be good to see if this could be optimized a
> little bit more, but I guess its similar to ntp_update_frequency()
> which is called on adjtimex() calls (every 16 seconds at most with
> networked ntp).
Well, this is not quite right. The interval is at least 4 seconds (1
<< PPS_FAVG) and increases if the signal is good. Maximum interval
length is 256 seconds (1 << PPS_FAVGDEF).
I don't see how it can be optimized right now.
> > +void hardpps(const struct timespec *p_ts, s64 nsec)
> > +{
> > + struct timespec ts_norm, freq_norm;
> > +
> > + ts_norm = pps_normalize_ts(*p_ts);
> > + freq_norm = pps_normalize_ts(ns_to_timespec(nsec));
> > +
> [snip]
> > +
> > + write_seqlock_irq(&xtime_lock);
>
> This is called possibly in irq context, right? So you probably want to
> use write_seqlock_irqsave(), no?
Right, thanks, it's bug. However, I think of moving it to a worqueue.
--
Alexander
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
next prev parent reply other threads:[~2010-02-03 23:52 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-03 20:56 [PATCH 0/5] pps: time synchronization over LPT Alexander Gordeev
2010-02-03 20:56 ` [PATCH 1/5] ntp: add hardpps implementation Alexander Gordeev
2010-02-03 22:08 ` john stultz
2010-02-03 23:51 ` Alexander Gordeev [this message]
2010-02-03 20:56 ` [PATCH 2/5] pps: capture MONOTONIC_RAW timestamps as well Alexander Gordeev
2010-02-03 22:26 ` john stultz
2010-02-04 11:05 ` Alexander Gordeev
2010-02-03 20:56 ` [PATCH 3/5] pps: add kernel consumer support Alexander Gordeev
2010-02-03 20:56 ` [PATCH 4/5] pps: add parallel port PPS signal generator Alexander Gordeev
2010-02-05 10:39 ` Rodolfo Giometti
2010-02-06 8:57 ` [LinuxPPS] " Alexander Gordeev
2010-02-03 20:56 ` [PATCH 5/5] pps: add parallel port PPS client Alexander Gordeev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100204025153.52fe962a@lvk.cs.msu.su \
--to=lasaine@lvk.cs.msu.su \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=giometti@enneenne.com \
--cc=giometti@linux.it \
--cc=johnstul@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxpps@ml.enneenne.com \
--cc=mingo@elte.hu \
--cc=riel@redhat.com \
--cc=stas@lvk.cs.msu.su \
--cc=tglx@linutronix.de \
--cc=yoush@cs.msu.su \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).