diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 115d55e11bc99cc2b55d0f155c99cfd2c2900443..91454dea2bc6f27aa1b8926364f4434c6b3a4768 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -29,6 +29,7 @@ struct timespec get_monotonic_coarse(void); extern void getrawmonotonic(struct timespec *ts); extern void ktime_get_ts64(struct timespec64 *ts); extern time64_t ktime_get_seconds(void); +extern time64_t ktime_get_real_seconds(void); extern int __getnstimeofday64(struct timespec64 *tv); extern void getnstimeofday64(struct timespec64 *tv); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index a693270efafba79c36bf87907b15daabc09c5a7f..0aef92a0a701fde5716e9222f6c1f6db3b14a011 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -676,6 +676,36 @@ time64_t ktime_get_seconds(void) } EXPORT_SYMBOL_GPL(ktime_get_seconds); +/** + * ktime_get_real_seconds - Get the seconds portion of CLOCK_REALTIME + * + * Returns the wall clock seconds since 1970. This replaces the + * get_seconds() interface which is not y2038 safe on 32bit systems. + * + * For 64bit systems the fast access to tk->xtime_sec is preserved. On + * 32bit systems the access must be protected with the sequence + * counter to provide "atomic" access to the 64bit tk->xtime_sec + * value. + */ +time64_t ktime_get_real_seconds(void) +{ + struct timekeeper *tk = &tk_core.timekeeper; + time64_t seconds; + unsigned int seq; + + if (IS_ENABLED(CONFIG_64BIT)) + return tk->xtime_sec; + + do { + seq = read_seqcount_begin(&tk_core.seq); + seconds = tk->xtime_sec; + + } while (read_seqcount_retry(&tk_core.seq, seq)); + + return seconds; +} +EXPORT_SYMBOL_GPL(ktime_get_real_seconds); + #ifdef CONFIG_NTP_PPS /**