From: Alexander Sverdlin <[email protected]>

Add CLOCK_MONOTONIC_RAW to the existing clock_gettime() vDSO
implementation. This is based on the ideas of Jason Vas Dias and comments
of Thomas Gleixner.

---- Test code ----
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>

 #define CLOCK_TYPE CLOCK_MONOTONIC_RAW
 #define DURATION_SEC 10

int main(int argc, char **argv)
{
        struct timespec t, end;
        unsigned long long cnt = 0;

        clock_gettime(CLOCK_TYPE, &end);
        end.tv_sec += DURATION_SEC;

        do {
                clock_gettime(CLOCK_TYPE, &t);
                ++cnt;
        } while (t.tv_sec < end.tv_sec || t.tv_nsec < end.tv_nsec);

        dprintf(STDOUT_FILENO, "%llu", cnt);

        return EXIT_SUCCESS;
}
-------------------

The results from the above test program:

Clock                   Before          After           Diff
-----                   ------          -----           ----
CLOCK_MONOTONIC         355531720       338039373       -5%
CLOCK_MONOTONIC_RAW     44831738        336064912       +650%
CLOCK_REALTIME          347665133       338102907       -3%

Link: https://lore.kernel.org/patchwork/patch/933583/
Link: https://bugzilla.kernel.org/show_bug.cgi?id=198961
Cc: Thomas Gleixner <[email protected]>
Cc: Jason Vas Dias <[email protected]>
Signed-off-by: Alexander Sverdlin <[email protected]>
---
 arch/x86/entry/vdso/vclock_gettime.c    | 11 +++++++++--
 arch/x86/entry/vsyscall/vsyscall_gtod.c |  6 ++++++
 arch/x86/include/asm/vgtod.h            |  5 ++++-
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/arch/x86/entry/vdso/vclock_gettime.c 
b/arch/x86/entry/vdso/vclock_gettime.c
index 98c7d12..7c9db26 100644
--- a/arch/x86/entry/vdso/vclock_gettime.c
+++ b/arch/x86/entry/vdso/vclock_gettime.c
@@ -144,6 +144,13 @@ notrace static int do_hres(clockid_t clk, struct timespec 
*ts)
        struct vgtod_ts *base = &gtod->basetime[clk];
        u64 cycles, last, sec, ns;
        unsigned int seq;
+       u32 mult = gtod->mult;
+       u32 shift = gtod->shift;
+
+       if (clk == CLOCK_MONOTONIC_RAW) {
+               mult = gtod->raw_mult;
+               shift = gtod->raw_shift;
+       }
 
        do {
                seq = gtod_read_begin(gtod);
@@ -153,8 +160,8 @@ notrace static int do_hres(clockid_t clk, struct timespec 
*ts)
                if (unlikely((s64)cycles < 0))
                        return vdso_fallback_gettime(clk, ts);
                if (cycles > last)
-                       ns += (cycles - last) * gtod->mult;
-               ns >>= gtod->shift;
+                       ns += (cycles - last) * mult;
+               ns >>= shift;
                sec = base->sec;
        } while (unlikely(gtod_read_retry(gtod, seq)));
 
diff --git a/arch/x86/entry/vsyscall/vsyscall_gtod.c 
b/arch/x86/entry/vsyscall/vsyscall_gtod.c
index cfcdba0..a967f02 100644
--- a/arch/x86/entry/vsyscall/vsyscall_gtod.c
+++ b/arch/x86/entry/vsyscall/vsyscall_gtod.c
@@ -46,11 +46,17 @@ void update_vsyscall(struct timekeeper *tk)
        vdata->mask             = tk->tkr_mono.mask;
        vdata->mult             = tk->tkr_mono.mult;
        vdata->shift            = tk->tkr_mono.shift;
+       vdata->raw_mult         = tk->tkr_raw.mult;
+       vdata->raw_shift        = tk->tkr_raw.shift;
 
        base = &vdata->basetime[CLOCK_REALTIME];
        base->sec = tk->xtime_sec;
        base->nsec = tk->tkr_mono.xtime_nsec;
 
+       base = &vdata->basetime[CLOCK_MONOTONIC_RAW];
+       base->sec = tk->raw_sec;
+       base->nsec = tk->tkr_raw.xtime_nsec;
+
        base = &vdata->basetime[CLOCK_TAI];
        base->sec = tk->xtime_sec + (s64)tk->tai_offset;
        base->nsec = tk->tkr_mono.xtime_nsec;
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index 913a133..f65c42b 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -28,7 +28,8 @@ struct vgtod_ts {
 };
 
 #define VGTOD_BASES    (CLOCK_TAI + 1)
-#define VGTOD_HRES     (BIT(CLOCK_REALTIME) | BIT(CLOCK_MONOTONIC) | 
BIT(CLOCK_TAI))
+#define VGTOD_HRES     (BIT(CLOCK_REALTIME) | BIT(CLOCK_MONOTONIC) | \
+                        BIT(CLOCK_MONOTONIC_RAW) | BIT(CLOCK_TAI))
 #define VGTOD_COARSE   (BIT(CLOCK_REALTIME_COARSE) | 
BIT(CLOCK_MONOTONIC_COARSE))
 
 /*
@@ -43,6 +44,8 @@ struct vsyscall_gtod_data {
        u64             mask;
        u32             mult;
        u32             shift;
+       u32             raw_mult;
+       u32             raw_shift;
 
        struct vgtod_ts basetime[VGTOD_BASES];
 
-- 
2.4.6

Reply via email to