From 4f0fad9a603aee91a374e8411c23953894a77479 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 27 Apr 2018 15:40:12 +0200 Subject: timekeeping: Remove timespec64 hack At this point, we have converted most of the kernel to use timespec64 consistently in place of timespec, so it seems it's time to make timespec64 the native structure and define timespec in terms of that one on 64-bit architectures. Starting with gcc-5, the compiler can completely optimize away the timespec_to_timespec64 and timespec64_to_timespec functions on 64-bit architectures. With older compilers, we introduce a couple of extra copies of local variables, but those are easily avoided by using the timespec64 based interfaces consistently, as we do in most of the important code paths already. The main upside of removing the hack is that printing the tv_sec field of a timespec64 structure can now use the %lld format string on all architectures without a cast to time64_t. Without this patch, the field is a 'long' type and would have to be printed using %ld on 64-bit architectures. Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Gleixner Cc: Stephen Boyd Cc: y2038@lists.linaro.org Cc: John Stultz Link: https://lkml.kernel.org/r/20180427134016.2525989-2-arnd@arndb.de --- kernel/time/time.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'kernel') diff --git a/kernel/time/time.c b/kernel/time/time.c index ccd751e95fcb..6fa99213fc72 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -407,7 +407,6 @@ time64_t mktime64(const unsigned int year0, const unsigned int mon0, } EXPORT_SYMBOL(mktime64); -#if __BITS_PER_LONG == 32 /** * set_normalized_timespec - set timespec sec and nsec parts and normalize * @@ -468,7 +467,6 @@ struct timespec ns_to_timespec(const s64 nsec) return ts; } EXPORT_SYMBOL(ns_to_timespec); -#endif /** * ns_to_timeval - Convert nanoseconds to timeval -- cgit v1.2.3-59-g8ed1b From edca71fecb77e2697337d192cbfe96f513407761 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 27 Apr 2018 15:40:13 +0200 Subject: timekeeping: Clean up ktime_get_real_ts64 In a move to make ktime_get_*() the preferred driver interface into the timekeeping code, sanitizes ktime_get_real_ts64() to be a proper exported symbol rather than an alias for getnstimeofday64(). The internal __getnstimeofday64() is no longer used, so remove that and merge it into ktime_get_real_ts64(). Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Gleixner Cc: Stephen Boyd Cc: y2038@lists.linaro.org Cc: John Stultz Link: https://lkml.kernel.org/r/20180427134016.2525989-3-arnd@arndb.de --- include/linux/timekeeping.h | 8 +++++--- include/linux/timekeeping32.h | 13 ++----------- kernel/time/timekeeping.c | 31 ++++++------------------------- 3 files changed, 13 insertions(+), 39 deletions(-) (limited to 'kernel') diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 588a0e4b1ab9..415dae6bf1f5 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -30,15 +30,13 @@ struct timespec64 current_kernel_time64(void); struct timespec64 get_monotonic_coarse64(void); extern void getrawmonotonic64(struct timespec64 *ts); extern void ktime_get_ts64(struct timespec64 *ts); +extern void ktime_get_real_ts64(struct timespec64 *tv); extern time64_t ktime_get_seconds(void); extern time64_t __ktime_get_real_seconds(void); extern time64_t ktime_get_real_seconds(void); -extern int __getnstimeofday64(struct timespec64 *tv); -extern void getnstimeofday64(struct timespec64 *tv); extern void getboottime64(struct timespec64 *ts); -#define ktime_get_real_ts64(ts) getnstimeofday64(ts) /* * ktime_t based interfaces @@ -210,5 +208,9 @@ extern void read_persistent_clock64(struct timespec64 *ts); extern void read_boot_clock64(struct timespec64 *ts); extern int update_persistent_clock64(struct timespec64 now); +/* + * deprecated aliases, don't use in new code + */ +#define getnstimeofday64(ts) ktime_get_real_ts64(ts) #endif diff --git a/include/linux/timekeeping32.h b/include/linux/timekeeping32.h index 4ea45d0df1d4..5abff52d07fd 100644 --- a/include/linux/timekeeping32.h +++ b/include/linux/timekeeping32.h @@ -27,20 +27,11 @@ static inline int do_settimeofday(const struct timespec *ts) return do_settimeofday64(&ts64); } -static inline int __getnstimeofday(struct timespec *ts) -{ - struct timespec64 ts64; - int ret = __getnstimeofday64(&ts64); - - *ts = timespec64_to_timespec(ts64); - return ret; -} - static inline void getnstimeofday(struct timespec *ts) { struct timespec64 ts64; - getnstimeofday64(&ts64); + ktime_get_real_ts64(&ts64); *ts = timespec64_to_timespec(ts64); } @@ -56,7 +47,7 @@ static inline void ktime_get_real_ts(struct timespec *ts) { struct timespec64 ts64; - getnstimeofday64(&ts64); + ktime_get_real_ts64(&ts64); *ts = timespec64_to_timespec(ts64); } diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 49cbceef5deb..7bbc7a6e6095 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -705,18 +705,19 @@ static void timekeeping_forward_now(struct timekeeper *tk) } /** - * __getnstimeofday64 - Returns the time of day in a timespec64. + * ktime_get_real_ts64 - Returns the time of day in a timespec64. * @ts: pointer to the timespec to be set * - * Updates the time of day in the timespec. - * Returns 0 on success, or -ve when suspended (timespec will be undefined). + * Returns the time of day in a timespec64 (WARN if suspended). */ -int __getnstimeofday64(struct timespec64 *ts) +void ktime_get_real_ts64(struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; unsigned long seq; u64 nsecs; + WARN_ON(timekeeping_suspended); + do { seq = read_seqcount_begin(&tk_core.seq); @@ -727,28 +728,8 @@ int __getnstimeofday64(struct timespec64 *ts) ts->tv_nsec = 0; timespec64_add_ns(ts, nsecs); - - /* - * Do not bail out early, in case there were callers still using - * the value, even in the face of the WARN_ON. - */ - if (unlikely(timekeeping_suspended)) - return -EAGAIN; - return 0; -} -EXPORT_SYMBOL(__getnstimeofday64); - -/** - * getnstimeofday64 - Returns the time of day in a timespec64. - * @ts: pointer to the timespec64 to be set - * - * Returns the time of day in a timespec64 (WARN if suspended). - */ -void getnstimeofday64(struct timespec64 *ts) -{ - WARN_ON(__getnstimeofday64(ts)); } -EXPORT_SYMBOL(getnstimeofday64); +EXPORT_SYMBOL(ktime_get_real_ts64); ktime_t ktime_get(void) { -- cgit v1.2.3-59-g8ed1b From fb7fcc96a86cfaef0f6dcc0665516aa68611e736 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 27 Apr 2018 15:40:14 +0200 Subject: timekeeping: Standardize on ktime_get_*() naming The current_kernel_time64, get_monotonic_coarse64, getrawmonotonic64, get_monotonic_boottime64 and timekeeping_clocktai64 interfaces have rather inconsistent naming, and they differ in the calling conventions by passing the output either by reference or as a return value. Rename them to ktime_get_coarse_real_ts64, ktime_get_coarse_ts64, ktime_get_raw_ts64, ktime_get_boottime_ts64 and ktime_get_clocktai_ts64 respectively, and provide the interfaces with macros or inline functions as needed. Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Gleixner Cc: Stephen Boyd Cc: y2038@lists.linaro.org Cc: John Stultz Link: https://lkml.kernel.org/r/20180427134016.2525989-4-arnd@arndb.de --- include/linux/timekeeping.h | 43 ++++++++++++++++++++++++++++++++----------- include/linux/timekeeping32.h | 14 ++++++++++---- kernel/time/timekeeping.c | 23 +++++++++-------------- 3 files changed, 51 insertions(+), 29 deletions(-) (limited to 'kernel') diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 415dae6bf1f5..3ef9791d7d75 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -19,25 +19,25 @@ extern void xtime_update(unsigned long ticks); extern int do_settimeofday64(const struct timespec64 *ts); extern int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz); -/* - * Kernel time accessors - */ -struct timespec64 current_kernel_time64(void); /* * timespec64 based interfaces */ -struct timespec64 get_monotonic_coarse64(void); -extern void getrawmonotonic64(struct timespec64 *ts); +extern void ktime_get_raw_ts64(struct timespec64 *ts); extern void ktime_get_ts64(struct timespec64 *ts); extern void ktime_get_real_ts64(struct timespec64 *tv); +extern void ktime_get_coarse_ts64(struct timespec64 *ts); +extern void ktime_get_coarse_real_ts64(struct timespec64 *ts); + +void getboottime64(struct timespec64 *ts); + +/* + * time64_t base interfaces + */ extern time64_t ktime_get_seconds(void); extern time64_t __ktime_get_real_seconds(void); extern time64_t ktime_get_real_seconds(void); -extern void getboottime64(struct timespec64 *ts); - - /* * ktime_t based interfaces */ @@ -123,12 +123,12 @@ extern u64 ktime_get_real_fast_ns(void); /* * timespec64 interfaces utilizing the ktime based ones */ -static inline void get_monotonic_boottime64(struct timespec64 *ts) +static inline void ktime_get_boottime_ts64(struct timespec64 *ts) { *ts = ktime_to_timespec64(ktime_get_boottime()); } -static inline void timekeeping_clocktai64(struct timespec64 *ts) +static inline void ktime_get_clocktai_ts64(struct timespec64 *ts) { *ts = ktime_to_timespec64(ktime_get_clocktai()); } @@ -212,5 +212,26 @@ extern int update_persistent_clock64(struct timespec64 now); * deprecated aliases, don't use in new code */ #define getnstimeofday64(ts) ktime_get_real_ts64(ts) +#define get_monotonic_boottime64(ts) ktime_get_boottime_ts64(ts) +#define getrawmonotonic64(ts) ktime_get_raw_ts64(ts) +#define timekeeping_clocktai64(ts) ktime_get_clocktai_ts64(ts) + +static inline struct timespec64 current_kernel_time64(void) +{ + struct timespec64 ts; + + ktime_get_coarse_real_ts64(&ts); + + return ts; +} + +static inline struct timespec64 get_monotonic_coarse64(void) +{ + struct timespec64 ts; + + ktime_get_coarse_ts64(&ts); + + return ts; +} #endif diff --git a/include/linux/timekeeping32.h b/include/linux/timekeeping32.h index 5abff52d07fd..8762c2f45f8b 100644 --- a/include/linux/timekeeping32.h +++ b/include/linux/timekeeping32.h @@ -11,9 +11,11 @@ unsigned long get_seconds(void); static inline struct timespec current_kernel_time(void) { - struct timespec64 now = current_kernel_time64(); + struct timespec64 ts64; + + ktime_get_coarse_real_ts64(&ts64); - return timespec64_to_timespec(now); + return timespec64_to_timespec(ts64); } /** @@ -55,13 +57,17 @@ static inline void getrawmonotonic(struct timespec *ts) { struct timespec64 ts64; - getrawmonotonic64(&ts64); + ktime_get_raw_ts64(&ts64); *ts = timespec64_to_timespec(ts64); } static inline struct timespec get_monotonic_coarse(void) { - return timespec64_to_timespec(get_monotonic_coarse64()); + struct timespec64 ts64; + + ktime_get_coarse_ts64(&ts64); + + return timespec64_to_timespec(ts64); } static inline void getboottime(struct timespec *ts) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 7bbc7a6e6095..ed9b74ec9c0b 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1391,12 +1391,12 @@ int timekeeping_notify(struct clocksource *clock) } /** - * getrawmonotonic64 - Returns the raw monotonic time in a timespec + * ktime_get_raw_ts64 - Returns the raw monotonic time in a timespec * @ts: pointer to the timespec64 to be set * * Returns the raw monotonic time (completely un-modified by ntp) */ -void getrawmonotonic64(struct timespec64 *ts) +void ktime_get_raw_ts64(struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; unsigned long seq; @@ -1412,7 +1412,7 @@ void getrawmonotonic64(struct timespec64 *ts) ts->tv_nsec = 0; timespec64_add_ns(ts, nsecs); } -EXPORT_SYMBOL(getrawmonotonic64); +EXPORT_SYMBOL(ktime_get_raw_ts64); /** @@ -2114,23 +2114,20 @@ unsigned long get_seconds(void) } EXPORT_SYMBOL(get_seconds); -struct timespec64 current_kernel_time64(void) +void ktime_get_coarse_real_ts64(struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; - struct timespec64 now; unsigned long seq; do { seq = read_seqcount_begin(&tk_core.seq); - now = tk_xtime(tk); + *ts = tk_xtime(tk); } while (read_seqcount_retry(&tk_core.seq, seq)); - - return now; } -EXPORT_SYMBOL(current_kernel_time64); +EXPORT_SYMBOL(ktime_get_coarse_real_ts64); -struct timespec64 get_monotonic_coarse64(void) +void ktime_get_coarse_ts64(struct timespec64 *ts) { struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 now, mono; @@ -2143,12 +2140,10 @@ struct timespec64 get_monotonic_coarse64(void) mono = tk->wall_to_monotonic; } while (read_seqcount_retry(&tk_core.seq, seq)); - set_normalized_timespec64(&now, now.tv_sec + mono.tv_sec, + set_normalized_timespec64(ts, now.tv_sec + mono.tv_sec, now.tv_nsec + mono.tv_nsec); - - return now; } -EXPORT_SYMBOL(get_monotonic_coarse64); +EXPORT_SYMBOL(ktime_get_coarse_ts64); /* * Must hold jiffies_lock -- cgit v1.2.3-59-g8ed1b From b9ff604cff1135cc576cf952d394ed9401aa234b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 27 Apr 2018 15:40:15 +0200 Subject: timekeeping: Add ktime_get_coarse_with_offset I have run into a couple of drivers using current_kernel_time() suffering from the y2038 problem, and they could be converted to using ktime_t, but don't have interfaces that skip the nanosecond calculation at the moment. This introduces ktime_get_coarse_with_offset() as a simpler variant of ktime_get_with_offset(), and adds wrappers for the three time domains we support with the existing function. Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Gleixner Cc: Stephen Boyd Cc: y2038@lists.linaro.org Cc: John Stultz Link: https://lkml.kernel.org/r/20180427134016.2525989-5-arnd@arndb.de --- include/linux/timekeeping.h | 16 ++++++++++++++++ kernel/time/timekeeping.c | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'kernel') diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 3ef9791d7d75..42f71f4b658a 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -51,6 +51,7 @@ enum tk_offsets { extern ktime_t ktime_get(void); extern ktime_t ktime_get_with_offset(enum tk_offsets offs); +extern ktime_t ktime_get_coarse_with_offset(enum tk_offsets offs); extern ktime_t ktime_mono_to_any(ktime_t tmono, enum tk_offsets offs); extern ktime_t ktime_get_raw(void); extern u32 ktime_get_resolution_ns(void); @@ -63,6 +64,11 @@ static inline ktime_t ktime_get_real(void) return ktime_get_with_offset(TK_OFFS_REAL); } +static inline ktime_t ktime_get_coarse_real(void) +{ + return ktime_get_coarse_with_offset(TK_OFFS_REAL); +} + /** * ktime_get_boottime - Returns monotonic time since boot in ktime_t format * @@ -74,6 +80,11 @@ static inline ktime_t ktime_get_boottime(void) return ktime_get_with_offset(TK_OFFS_BOOT); } +static inline ktime_t ktime_get_coarse_boottime(void) +{ + return ktime_get_coarse_with_offset(TK_OFFS_BOOT); +} + /** * ktime_get_clocktai - Returns the TAI time of day in ktime_t format */ @@ -82,6 +93,11 @@ static inline ktime_t ktime_get_clocktai(void) return ktime_get_with_offset(TK_OFFS_TAI); } +static inline ktime_t ktime_get_coarse_clocktai(void) +{ + return ktime_get_coarse_with_offset(TK_OFFS_TAI); +} + /** * ktime_mono_to_real - Convert monotonic time to clock realtime */ diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index ed9b74ec9c0b..4786df904c22 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -795,6 +795,25 @@ ktime_t ktime_get_with_offset(enum tk_offsets offs) } EXPORT_SYMBOL_GPL(ktime_get_with_offset); +ktime_t ktime_get_coarse_with_offset(enum tk_offsets offs) +{ + struct timekeeper *tk = &tk_core.timekeeper; + unsigned int seq; + ktime_t base, *offset = offsets[offs]; + + WARN_ON(timekeeping_suspended); + + do { + seq = read_seqcount_begin(&tk_core.seq); + base = ktime_add(tk->tkr_mono.base, *offset); + + } while (read_seqcount_retry(&tk_core.seq, seq)); + + return base; + +} +EXPORT_SYMBOL_GPL(ktime_get_coarse_with_offset); + /** * ktime_mono_to_any() - convert mononotic time to any other time * @tmono: time to convert. -- cgit v1.2.3-59-g8ed1b