Skip to content

Commit 5b9fe75

Browse files
committed
timekeeping: Maintain ktime_t based offsets for hrtimers
We need to update the hrtimer clock offsets from the hrtimer interrupt context. To avoid conversions from timespec to ktime_t maintain a ktime_t based representation of those offsets in the timekeeper. This puts the conversion overhead into the code which updates the underlying offsets and provides fast accessible values in the hrtimer interrupt. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: John Stultz <johnstul@us.ibm.com> Reviewed-by: Ingo Molnar <mingo@kernel.org> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Prarit Bhargava <prarit@redhat.com> Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1341960205-56738-4-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent 4873fa0 commit 5b9fe75

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

kernel/time/timekeeping.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ struct timekeeper {
7070
/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
7171
struct timespec raw_time;
7272

73+
/* Offset clock monotonic -> clock realtime */
74+
ktime_t offs_real;
75+
76+
/* Offset clock monotonic -> clock boottime */
77+
ktime_t offs_boot;
78+
7379
/* Seqlock for all timekeeper values */
7480
seqlock_t lock;
7581
};
@@ -172,13 +178,22 @@ static inline s64 timekeeping_get_ns_raw(void)
172178
return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
173179
}
174180

181+
static void update_rt_offset(void)
182+
{
183+
struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic;
184+
185+
set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
186+
timekeeper.offs_real = timespec_to_ktime(tmp);
187+
}
188+
175189
/* must hold write on timekeeper.lock */
176190
static void timekeeping_update(bool clearntp)
177191
{
178192
if (clearntp) {
179193
timekeeper.ntp_error = 0;
180194
ntp_clear();
181195
}
196+
update_rt_offset();
182197
update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic,
183198
timekeeper.clock, timekeeper.mult);
184199
}
@@ -604,6 +619,7 @@ void __init timekeeping_init(void)
604619
}
605620
set_normalized_timespec(&timekeeper.wall_to_monotonic,
606621
-boot.tv_sec, -boot.tv_nsec);
622+
update_rt_offset();
607623
timekeeper.total_sleep_time.tv_sec = 0;
608624
timekeeper.total_sleep_time.tv_nsec = 0;
609625
write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -612,6 +628,12 @@ void __init timekeeping_init(void)
612628
/* time in seconds when suspend began */
613629
static struct timespec timekeeping_suspend_time;
614630

631+
static void update_sleep_time(struct timespec t)
632+
{
633+
timekeeper.total_sleep_time = t;
634+
timekeeper.offs_boot = timespec_to_ktime(t);
635+
}
636+
615637
/**
616638
* __timekeeping_inject_sleeptime - Internal function to add sleep interval
617639
* @delta: pointer to a timespec delta value
@@ -630,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
630652
timekeeper.xtime = timespec_add(timekeeper.xtime, *delta);
631653
timekeeper.wall_to_monotonic =
632654
timespec_sub(timekeeper.wall_to_monotonic, *delta);
633-
timekeeper.total_sleep_time = timespec_add(
634-
timekeeper.total_sleep_time, *delta);
655+
update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta));
635656
}
636657

637658

0 commit comments

Comments
 (0)