Merge branch 'timers-2038-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull more 2038 timer work from Thomas Gleixner: "Two more patches for the ongoing 2038 work: - New accessors to clock MONOTONIC and REALTIME seconds This is a seperate branch as Arnd has follow up work depending on this" * 'timers-2038-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: timekeeping: Provide y2038 safe accessor to the seconds portion of CLOCK_REALTIME timekeeping: Provide fast accessor to the seconds part of CLOCK_MONOTONIC
This commit is contained in:
commit
d82012695e
@ -42,6 +42,7 @@ struct tk_read_base {
|
|||||||
* struct timekeeper - Structure holding internal timekeeping values.
|
* struct timekeeper - Structure holding internal timekeeping values.
|
||||||
* @tkr: The readout base structure
|
* @tkr: The readout base structure
|
||||||
* @xtime_sec: Current CLOCK_REALTIME time in seconds
|
* @xtime_sec: Current CLOCK_REALTIME time in seconds
|
||||||
|
* @ktime_sec: Current CLOCK_MONOTONIC time in seconds
|
||||||
* @wall_to_monotonic: CLOCK_REALTIME to CLOCK_MONOTONIC offset
|
* @wall_to_monotonic: CLOCK_REALTIME to CLOCK_MONOTONIC offset
|
||||||
* @offs_real: Offset clock monotonic -> clock realtime
|
* @offs_real: Offset clock monotonic -> clock realtime
|
||||||
* @offs_boot: Offset clock monotonic -> clock boottime
|
* @offs_boot: Offset clock monotonic -> clock boottime
|
||||||
@ -77,6 +78,7 @@ struct tk_read_base {
|
|||||||
struct timekeeper {
|
struct timekeeper {
|
||||||
struct tk_read_base tkr;
|
struct tk_read_base tkr;
|
||||||
u64 xtime_sec;
|
u64 xtime_sec;
|
||||||
|
unsigned long ktime_sec;
|
||||||
struct timespec64 wall_to_monotonic;
|
struct timespec64 wall_to_monotonic;
|
||||||
ktime_t offs_real;
|
ktime_t offs_real;
|
||||||
ktime_t offs_boot;
|
ktime_t offs_boot;
|
||||||
|
@ -28,6 +28,8 @@ struct timespec __current_kernel_time(void);
|
|||||||
struct timespec64 get_monotonic_coarse64(void);
|
struct timespec64 get_monotonic_coarse64(void);
|
||||||
extern void getrawmonotonic64(struct timespec64 *ts);
|
extern void getrawmonotonic64(struct timespec64 *ts);
|
||||||
extern void ktime_get_ts64(struct timespec64 *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 int __getnstimeofday64(struct timespec64 *tv);
|
||||||
extern void getnstimeofday64(struct timespec64 *tv);
|
extern void getnstimeofday64(struct timespec64 *tv);
|
||||||
|
@ -417,7 +417,8 @@ EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier);
|
|||||||
*/
|
*/
|
||||||
static inline void tk_update_ktime_data(struct timekeeper *tk)
|
static inline void tk_update_ktime_data(struct timekeeper *tk)
|
||||||
{
|
{
|
||||||
s64 nsec;
|
u64 seconds;
|
||||||
|
u32 nsec;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The xtime based monotonic readout is:
|
* The xtime based monotonic readout is:
|
||||||
@ -426,13 +427,22 @@ static inline void tk_update_ktime_data(struct timekeeper *tk)
|
|||||||
* nsec = base_mono + now();
|
* nsec = base_mono + now();
|
||||||
* ==> base_mono = (xtime_sec + wtm_sec) * 1e9 + wtm_nsec
|
* ==> base_mono = (xtime_sec + wtm_sec) * 1e9 + wtm_nsec
|
||||||
*/
|
*/
|
||||||
nsec = (s64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec);
|
seconds = (u64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec);
|
||||||
nsec *= NSEC_PER_SEC;
|
nsec = (u32) tk->wall_to_monotonic.tv_nsec;
|
||||||
nsec += tk->wall_to_monotonic.tv_nsec;
|
tk->tkr.base_mono = ns_to_ktime(seconds * NSEC_PER_SEC + nsec);
|
||||||
tk->tkr.base_mono = ns_to_ktime(nsec);
|
|
||||||
|
|
||||||
/* Update the monotonic raw base */
|
/* Update the monotonic raw base */
|
||||||
tk->base_raw = timespec64_to_ktime(tk->raw_time);
|
tk->base_raw = timespec64_to_ktime(tk->raw_time);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The sum of the nanoseconds portions of xtime and
|
||||||
|
* wall_to_monotonic can be greater/equal one second. Take
|
||||||
|
* this into account before updating tk->ktime_sec.
|
||||||
|
*/
|
||||||
|
nsec += (u32)(tk->tkr.xtime_nsec >> tk->tkr.shift);
|
||||||
|
if (nsec >= NSEC_PER_SEC)
|
||||||
|
seconds++;
|
||||||
|
tk->ktime_sec = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must hold timekeeper_lock */
|
/* must hold timekeeper_lock */
|
||||||
@ -648,6 +658,54 @@ void ktime_get_ts64(struct timespec64 *ts)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ktime_get_ts64);
|
EXPORT_SYMBOL_GPL(ktime_get_ts64);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ktime_get_seconds - Get the seconds portion of CLOCK_MONOTONIC
|
||||||
|
*
|
||||||
|
* Returns the seconds portion of CLOCK_MONOTONIC with a single non
|
||||||
|
* serialized read. tk->ktime_sec is of type 'unsigned long' so this
|
||||||
|
* works on both 32 and 64 bit systems. On 32 bit systems the readout
|
||||||
|
* covers ~136 years of uptime which should be enough to prevent
|
||||||
|
* premature wrap arounds.
|
||||||
|
*/
|
||||||
|
time64_t ktime_get_seconds(void)
|
||||||
|
{
|
||||||
|
struct timekeeper *tk = &tk_core.timekeeper;
|
||||||
|
|
||||||
|
WARN_ON(timekeeping_suspended);
|
||||||
|
return tk->ktime_sec;
|
||||||
|
}
|
||||||
|
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
|
#ifdef CONFIG_NTP_PPS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user