Message ID | 20190619142350.1985-1-Jason@zx2c4.com |
---|---|
State | New |
Headers | show |
Series | [v2] timekeeping: get_jiffies_boot_64() for jiffies that include sleep time | expand |
On Wed, Jun 19, 2019 at 4:24 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote: > > This enables using the usual get_jiffies_64() but taking into account > time spent sleeping, giving the high performance characteristics of > querying jiffies without the drawback. Can you quantify how much this gains you over ktime_get_coarse_boottime in practice? You are effectively adding yet another abstraction for time, which is something I'd hope to avoid unless you have a strong reason other than it being faster in theory. How often do you read the current time? Arnd
Hi Arnd, On Wed, Jun 19, 2019 at 5:08 PM Arnd Bergmann <arnd@arndb.de> wrote: > Can you quantify how much this gains you over ktime_get_coarse_boottime > in practice? You are effectively adding yet another abstraction for time, > which is something I'd hope to avoid unless you have a strong reason other > than it being faster in theory. Excellent idea. It turns out to be precisely 0 (see below). A motivation still remains, though: this allows comparison with units specified in terms of jiffies, which means that the unit being compared matches the exact tick of the clock, making those comparisons as precise as possible, for what they are. I suppose you could argue, on the other hand, that nanoseconds give so much precision already, that approximations using them amount practically to the same thing. I'm not sure which way to reason about that. For interest, here are a few comparisons taken with kbench9000: get_jiffies_boot_64 26 ktime_get_coarse_boottime 26 ktime_get_boot_fast_ns with tsc 70 ktime_get_boot_fast_ns with hpet 4922 ktime_get_boot_fast_ns with acpi_pm 1884 As expected, hpet is really quite painful. Jason
On Wed, Jun 19, 2019 at 5:31 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote: > > Hi Arnd, > > On Wed, Jun 19, 2019 at 5:08 PM Arnd Bergmann <arnd@arndb.de> wrote: > > Can you quantify how much this gains you over ktime_get_coarse_boottime > > in practice? You are effectively adding yet another abstraction for time, > > which is something I'd hope to avoid unless you have a strong reason other > > than it being faster in theory. > > Excellent idea. It turns out to be precisely 0 (see below). A > motivation still remains, though: this allows comparison with units > specified in terms of jiffies, which means that the unit being > compared matches the exact tick of the clock, making those comparisons > as precise as possible, for what they are. I suppose you could argue, > on the other hand, that nanoseconds give so much precision already, > that approximations using them amount practically to the same thing. > I'm not sure which way to reason about that. > > For interest, here are a few comparisons taken with kbench9000: > > get_jiffies_boot_64 26 > ktime_get_coarse_boottime 26 > ktime_get_boot_fast_ns with tsc 70 > ktime_get_boot_fast_ns with hpet 4922 > ktime_get_boot_fast_ns with acpi_pm 1884 > > As expected, hpet is really quite painful. I would prefer not to add the new interface then. We might in fact move users of get_jiffies_64() to ktime_get_coarse() for consistency given the small overhead of that function. Arnd
On Wed, Jun 19, 2019 at 10:02 PM Arnd Bergmann <arnd@arndb.de> wrote: > > get_jiffies_boot_64 26 > > ktime_get_coarse_boottime 26 > > ktime_get_boot_fast_ns with tsc 70 > > ktime_get_boot_fast_ns with hpet 4922 > > ktime_get_boot_fast_ns with acpi_pm 1884 > > > > As expected, hpet is really quite painful. > > I would prefer not to add the new interface then. We might in > fact move users of get_jiffies_64() to ktime_get_coarse() for > consistency given the small overhead of that function. In light of the measurements, that seems like a good plan to me. One thing to consider with moving jiffies users over that way is ktime_t. Do you want to introduce helpers like ktime_get_boot_coarse_ns(), just like there is already with the other various functions like ktime_get_boot_ns(), ktime_get_boot_fast_ns(), etc? (I'd personally prefer using the _ns variants, at least.) I can send a patch for this. Jason
On Wed, Jun 19, 2019 at 10:07 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote: > > On Wed, Jun 19, 2019 at 10:02 PM Arnd Bergmann <arnd@arndb.de> wrote: > > > get_jiffies_boot_64 26 > > > ktime_get_coarse_boottime 26 > > > ktime_get_boot_fast_ns with tsc 70 > > > ktime_get_boot_fast_ns with hpet 4922 > > > ktime_get_boot_fast_ns with acpi_pm 1884 > > > > > > As expected, hpet is really quite painful. > > > > I would prefer not to add the new interface then. We might in > > fact move users of get_jiffies_64() to ktime_get_coarse() for > > consistency given the small overhead of that function. > > In light of the measurements, that seems like a good plan to me. > > One thing to consider with moving jiffies users over that way is > ktime_t. Do you want to introduce helpers like > ktime_get_boot_coarse_ns(), just like there is already with the other > various functions like ktime_get_boot_ns(), ktime_get_boot_fast_ns(), > etc? (I'd personally prefer using the _ns variants, at least.) I can > send a patch for this. That sounds reasonable, but then I think we should have the full set of coarse_*_ns() functions, again for consistency: u64 ktime_get_coarse_ns(void) u64 ktime_get_coarse_boottime_ns(void) u64 ktime_get_coarse_real_ns(void) u64 ktime_get_coarse_clocktai_ns(void) and document them in Documentation/core-api/timekeeping.rst. We seem to also be lacking the basic ktime_get_coarse(), which seems like a major omission. Both ktime_get_coarse_ns and ktime_get_coarse can be wrappers around ktime_get_coarse_ts64() then, while the others would use ktime_get_coarse_with_offset(). Arnd
On Wed, Jun 19, 2019 at 10:57 PM Arnd Bergmann <arnd@arndb.de> wrote: > > On Wed, Jun 19, 2019 at 10:07 PM Jason A. Donenfeld <Jason@zx2c4.com> wrote: > > > > On Wed, Jun 19, 2019 at 10:02 PM Arnd Bergmann <arnd@arndb.de> wrote: > > > > get_jiffies_boot_64 26 > > > > ktime_get_coarse_boottime 26 > > > > ktime_get_boot_fast_ns with tsc 70 > > > > ktime_get_boot_fast_ns with hpet 4922 > > > > ktime_get_boot_fast_ns with acpi_pm 1884 > > > > > > > > As expected, hpet is really quite painful. > > > > > > I would prefer not to add the new interface then. We might in > > > fact move users of get_jiffies_64() to ktime_get_coarse() for > > > consistency given the small overhead of that function. > > > > In light of the measurements, that seems like a good plan to me. > > > > One thing to consider with moving jiffies users over that way is > > ktime_t. Do you want to introduce helpers like > > ktime_get_boot_coarse_ns(), just like there is already with the other > > various functions like ktime_get_boot_ns(), ktime_get_boot_fast_ns(), > > etc? (I'd personally prefer using the _ns variants, at least.) I can > > send a patch for this. > > That sounds reasonable, but then I think we should have the full > set of coarse_*_ns() functions, again for consistency: > > u64 ktime_get_coarse_ns(void) > u64 ktime_get_coarse_boottime_ns(void) > u64 ktime_get_coarse_real_ns(void) > u64 ktime_get_coarse_clocktai_ns(void) > > and document them in Documentation/core-api/timekeeping.rst. > > We seem to also be lacking the basic ktime_get_coarse(), which > seems like a major omission. > Both ktime_get_coarse_ns and ktime_get_coarse can be wrappers > around ktime_get_coarse_ts64() then, while the others would > use ktime_get_coarse_with_offset(). Exactly what I had in mind. I'll have something posted fairly soon. Jason
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 1b6d31da7cbc..e4a9776d8b2a 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -80,6 +80,7 @@ extern int register_refined_jiffies(long clock_tick_rate); extern u64 __cacheline_aligned_in_smp jiffies_64; extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies; +u64 get_jiffies_boot_64(void); #if (BITS_PER_LONG < 64) u64 get_jiffies_64(void); #else diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index 7acb953298a7..2e4c52fe0250 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -51,6 +51,7 @@ struct tk_read_base { * @wall_to_monotonic: CLOCK_REALTIME to CLOCK_MONOTONIC offset * @offs_real: Offset clock monotonic -> clock realtime * @offs_boot: Offset clock monotonic -> clock boottime + * @offs_boot_jiffies64 Offset clock monotonic -> clock boottime in jiffies64 * @offs_tai: Offset clock monotonic -> clock tai * @tai_offset: The current UTC to TAI offset in seconds * @clock_was_set_seq: The sequence number of clock was set events @@ -93,6 +94,7 @@ struct timekeeper { struct timespec64 wall_to_monotonic; ktime_t offs_real; ktime_t offs_boot; + u64 offs_boot_jiffies64; ktime_t offs_tai; s32 tai_offset; unsigned int clock_was_set_seq; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 85f5912d8f70..a3707b454446 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -146,6 +146,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec64 wtm) static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta) { tk->offs_boot = ktime_add(tk->offs_boot, delta); + tk->offs_boot_jiffies64 = nsecs_to_jiffies64(ktime_to_ns(tk->offs_boot)); } /* @@ -539,6 +540,16 @@ u64 ktime_get_real_fast_ns(void) } EXPORT_SYMBOL_GPL(ktime_get_real_fast_ns); +/** + * get_jiffies_boot_64 - The normal get_jiffies_64(), but taking into + * account the time spent sleeping. + */ +u64 get_jiffies_boot_64(void) +{ + return get_jiffies_64() + tk_core.timekeeper.offs_boot_jiffies64; +} +EXPORT_SYMBOL(get_jiffies_boot_64); + /** * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. * @tk: Timekeeper to snapshot.
This enables using the usual get_jiffies_64() but taking into account time spent sleeping, giving the high performance characteristics of querying jiffies without the drawback. We accomplish this by precomputing the boottime jiffies offset whenever it is updated, rather than doing the expensive-ish div_u64 on each query. Since the resolution of this is in terms of jiffies, this allows determining limits for comparison in terms of jiffies too, which makes the comparisons more exact, despite jiffies being a fairly coarse stamp. Adding the suspend offset to jiffies as such doesn't actually race in a way different from the usual races associated with the suspend offset: either boot offset has been updated before the call to get_jiffies_boot_64(), in which case we're fine, or it hasn't in which case, this is no different than any of the existing suspend querying functions, which may be invoked early in system resumption before the offset is updated. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Andrew Morton <akpm@linux-foundation.org> Cc; John Stultz <john.stultz@linaro.org> --- include/linux/jiffies.h | 1 + include/linux/timekeeper_internal.h | 2 ++ kernel/time/timekeeping.c | 11 +++++++++++ 3 files changed, 14 insertions(+) -- 2.21.0