The ktime_t based interfaces are used a lot in performance critical
code pathes. Add ktime_t based data so the interfaces don't have to
convert from the xtime/timespec based data.

Signed-off-by: Thomas Gleixner <[email protected]>
---
 include/linux/timekeeper_internal.h |    3 +++
 kernel/time/timekeeping.c           |   25 +++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

Index: tip/include/linux/timekeeper_internal.h
===================================================================
--- tip.orig/include/linux/timekeeper_internal.h
+++ tip/include/linux/timekeeper_internal.h
@@ -36,6 +36,9 @@ struct timekeeper {
        /* Clock shifted nano seconds */
        u64                     xtime_nsec;
 
+       /* Monotonic base time */
+       ktime_t                 base_mono;
+
        /* Current CLOCK_REALTIME time in seconds */
        u64                     xtime_sec;
        /* CLOCK_REALTIME to CLOCK_MONOTONIC offset */
Index: tip/kernel/time/timekeeping.c
===================================================================
--- tip.orig/kernel/time/timekeeping.c
+++ tip/kernel/time/timekeeping.c
@@ -50,12 +50,30 @@ int __read_mostly timekeeping_suspended;
 /* Flag for if there is a persistent clock on this platform */
 bool __read_mostly persistent_clock_exist = false;
 
+/*
+ * The xtime based monotonic readout is:
+ *     nsec = (xtime_sec + wtm_sec) * 1e9 + wtm_nsec + now();
+ * The ktime based monotonic readout is:
+ *     nsec = base_mono + now();
+ * ==> base_mono = (xtime_sec + wtm_sec) * 1e9 + wtm_nsec
+ */
+static inline void tk_update_ktime_base(struct timekeeper *tk)
+{
+       s64 nsec;
+
+       nsec = (s64)(tk->xtime_sec + tk->wall_to_monotonic.tv_sec);
+       nsec *= NSEC_PER_SEC;
+       nsec += tk->wall_to_monotonic.tv_nsec;
+       tk->base_mono = ns_to_ktime(nsec);
+}
+
 static inline void tk_normalize_xtime(struct timekeeper *tk)
 {
        while (tk->xtime_nsec >= ((u64)NSEC_PER_SEC << tk->shift)) {
                tk->xtime_nsec -= (u64)NSEC_PER_SEC << tk->shift;
                tk->xtime_sec++;
        }
+       tk_update_ktime_base(tk);
 }
 
 static inline struct timespec64 tk_xtime(struct timekeeper *tk)
@@ -71,6 +89,7 @@ static void tk_set_xtime(struct timekeep
 {
        tk->xtime_sec = ts->tv_sec;
        tk->xtime_nsec = (u64)ts->tv_nsec << tk->shift;
+       tk_update_ktime_base(tk);
 }
 
 static void tk_xtime_add(struct timekeeper *tk, const struct timespec64 *ts)
@@ -93,6 +112,7 @@ static void tk_set_wall_to_mono(struct t
        WARN_ON_ONCE(tk->offs_real.tv64 != timespec64_to_ktime(tmp).tv64);
        tk->wall_to_monotonic = wtm;
        set_normalized_timespec64(&tmp, -wtm.tv_sec, -wtm.tv_nsec);
+       tk_update_ktime_base(tk);
        tk->offs_real = timespec64_to_ktime(tmp);
        tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tk->tai_offset, 0));
 }
@@ -329,6 +349,7 @@ static void timekeeping_forward_now(stru
        /* If arch requires, add in get_arch_timeoffset() */
        tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift;
 
+       /* Updates tk->base_mono as well */
        tk_normalize_xtime(tk);
 
        nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
@@ -1448,6 +1469,10 @@ void update_wall_time(void)
         * xtime_nsec isn't larger than NSEC_PER_SEC
         */
        clock_set |= accumulate_nsecs_to_secs(tk);
+       /*
+        * Update the monotonic base
+        */
+       tk_update_ktime_base(tk);
 
        write_seqcount_begin(&tk_core.seq);
        /* Update clock->cycle_last with the new value */


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to