Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1650434 > unrolled thread

Re: [RFC][PATCH] time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD

Started byPaul Mackerras <paulus@ozlabs.org>
First post2017-05-25 14:10 +0200
Last post2017-05-27 06:30 +0200
Articles 2 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [RFC][PATCH] time: Add warning about imminent deprecation of  CONFIG_GENERIC_TIME_VSYSCALL_OLD Paul Mackerras <paulus@ozlabs.org> - 2017-05-25 14:10 +0200
    Re: [RFC][PATCH] time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD John Stultz <john.stultz@linaro.org> - 2017-05-27 06:30 +0200

#1650434 — Re: [RFC][PATCH] time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD

FromPaul Mackerras <paulus@ozlabs.org>
Date2017-05-25 14:10 +0200
SubjectRe: [RFC][PATCH] time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD
Message-ID<tKZKx-81K-7@gated-at.bofh.it>
On Mon, May 22, 2017 at 12:06:04PM -0700, John Stultz wrote:
> 
> Basically long ago, timekeeping was handled (roughly) like:
> 
> clock_gettime():
>     now = tk->clock->read()
>     offset_ns = ((now - tk->cycle_last) * tk->clock->mult) >> tk->clock->shift;
>     return timespec_add_ns(tk->xtime, offset_ns);
> 
> But since for error handling use sub-ns precision, combined with that
> for update performance, we accumulate in fixed intervals, there are
> situations where in the update, we could accumulate half of a
> nanosecond into the base tk->xtime value and leaving half of a
> nanosecond in the offset.   This caused the split nanosecond to be
> truncated out by the math, causing 1ns discontinuities.
> 
> So to address this, we came up with sort of a hack, which when we
> accumulate rounds up that partial nanosecond, and adds the amount we
> rounded up to the error (which will cause the freq correction code to
> slow the clock down slightly). This is the code that is now done in
> the old_vsyscall_fixup() logic.
> 
> Unfortunately this fix (which generates up to a nanosecond of error
> per tick) then made the freq correction code do more work and made it
> more difficult to have a stable clock.
> 
> So we went for a more proper fix, which was to properly handle the
> sub-nanosecond portion of the timekeeping throughout the logic, doing
> the truncation last.
> 
> clock_gettime():
>     now = tk->clock->read()
>     ret.tv_sec = tk->xtime_sec;
>     offset_sns = (now - tk->cycle_last) * tk->clock->mult;
>     ret.tv_nsec = (offset_sns + tk->tkr_mono.xtime_nsec) >> tk->clock->shift;
>     return ret;
> 
> So in the above, we now use the tk->tkr_mono.xtime_nsec (which despite
> its unfortunate name, stores the accumulated shifted nanoseconds), and
> add it to the (current_cycle_delta * clock->mult), then we do the
> shift last to preserve as much precision as we can.
> 
> Unfortunately we need all the reader code to do the same, which wasn't
> easy to transition in some cases. So we provided the
> CONFIG_GENERIC_TIME_VSYSCALL_OLD option to preserve the old round-up
> behavior while arch maintainers could make the transition.

The VDSO code on PPC computes the offset in units of 2^-32 seconds,
not nanoseconds, because that makes it easy to handle the split of the
offset into whole seconds and fractional seconds (which is handled in
the generic code by the slightly icky __iter_div_u64_rem function),
and also means that we can use PPC's instruction that computes
(a * b) >> 32 to convert the fractional part to either nanoseconds or
microseconds without doing a division.

I could pretty easily change the computations done at update_vsyscall
time to convert the tk->tkr_mono.xtime_nsec value to units of 2^-32
seconds for use by the VDSO.  That would mean we would no longer need
CONFIG_GENERIC_TIME_VSYSCALL_OLD, and would give us values returned by
the VDSO gettimeofday() and clock_gettime() that should be within
about 1/4 ns of what the generic code in the kernel would give (on
average, I mean, given that the results have at best nanosecond
resolution).  Since that corresponds to about 1 CPU clock cycle, it
seems like it should be good enough.

Alternatively I could make the VDSO computations use a smaller unit
(maybe 2^-36 or 2^-40 seconds), or else rewrite them to use exactly
the same algorithm as the generic code - which would be a bigger
change, and would mean having to do an iterative division.

So, do you think the 1/4 ns resolution is good enough for the VDSO
computations?

Paul.

[toc] | [next] | [standalone]


#1651753 — Re: [RFC][PATCH] time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD

FromJohn Stultz <john.stultz@linaro.org>
Date2017-05-27 06:30 +0200
SubjectRe: [RFC][PATCH] time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD
Message-ID<tLBwu-6RP-5@gated-at.bofh.it>
In reply to#1650434
On Thu, May 25, 2017 at 5:03 AM, Paul Mackerras <paulus@ozlabs.org> wrote:
> On Mon, May 22, 2017 at 12:06:04PM -0700, John Stultz wrote:
>>
>> Basically long ago, timekeeping was handled (roughly) like:
>>
>> clock_gettime():
>>     now = tk->clock->read()
>>     offset_ns = ((now - tk->cycle_last) * tk->clock->mult) >> tk->clock->shift;
>>     return timespec_add_ns(tk->xtime, offset_ns);
>>
>> But since for error handling use sub-ns precision, combined with that
>> for update performance, we accumulate in fixed intervals, there are
>> situations where in the update, we could accumulate half of a
>> nanosecond into the base tk->xtime value and leaving half of a
>> nanosecond in the offset.   This caused the split nanosecond to be
>> truncated out by the math, causing 1ns discontinuities.
>>
>> So to address this, we came up with sort of a hack, which when we
>> accumulate rounds up that partial nanosecond, and adds the amount we
>> rounded up to the error (which will cause the freq correction code to
>> slow the clock down slightly). This is the code that is now done in
>> the old_vsyscall_fixup() logic.
>>
>> Unfortunately this fix (which generates up to a nanosecond of error
>> per tick) then made the freq correction code do more work and made it
>> more difficult to have a stable clock.
>>
>> So we went for a more proper fix, which was to properly handle the
>> sub-nanosecond portion of the timekeeping throughout the logic, doing
>> the truncation last.
>>
>> clock_gettime():
>>     now = tk->clock->read()
>>     ret.tv_sec = tk->xtime_sec;
>>     offset_sns = (now - tk->cycle_last) * tk->clock->mult;
>>     ret.tv_nsec = (offset_sns + tk->tkr_mono.xtime_nsec) >> tk->clock->shift;
>>     return ret;
>>
>> So in the above, we now use the tk->tkr_mono.xtime_nsec (which despite
>> its unfortunate name, stores the accumulated shifted nanoseconds), and
>> add it to the (current_cycle_delta * clock->mult), then we do the
>> shift last to preserve as much precision as we can.
>>
>> Unfortunately we need all the reader code to do the same, which wasn't
>> easy to transition in some cases. So we provided the
>> CONFIG_GENERIC_TIME_VSYSCALL_OLD option to preserve the old round-up
>> behavior while arch maintainers could make the transition.
>
> The VDSO code on PPC computes the offset in units of 2^-32 seconds,
> not nanoseconds, because that makes it easy to handle the split of the
> offset into whole seconds and fractional seconds (which is handled in
> the generic code by the slightly icky __iter_div_u64_rem function),
> and also means that we can use PPC's instruction that computes
> (a * b) >> 32 to convert the fractional part to either nanoseconds or
> microseconds without doing a division.
>
> I could pretty easily change the computations done at update_vsyscall
> time to convert the tk->tkr_mono.xtime_nsec value to units of 2^-32
> seconds for use by the VDSO.  That would mean we would no longer need
> CONFIG_GENERIC_TIME_VSYSCALL_OLD, and would give us values returned by
> the VDSO gettimeofday() and clock_gettime() that should be within
> about 1/4 ns of what the generic code in the kernel would give (on
> average, I mean, given that the results have at best nanosecond
> resolution).  Since that corresponds to about 1 CPU clock cycle, it
> seems like it should be good enough.
>
> Alternatively I could make the VDSO computations use a smaller unit
> (maybe 2^-36 or 2^-40 seconds), or else rewrite them to use exactly
> the same algorithm as the generic code - which would be a bigger
> change, and would mean having to do an iterative division.
>
> So, do you think the 1/4 ns resolution is good enough for the VDSO
> computations?

Sorry not to have gotten back to you yesterday on this!  So yea, the
above sounds reasonable to me. We only return ns resolution to
userspace, so I don't believe one would be able to make a normal
syscall that calculates time and then make a gettime call within a
1/4th of a nanosecond.

But, I can't say I've ever really groked the ppc logic, so take my
opinion with a grain of salt. :)

thanks
-john

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web