]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vdso/gettimeofday: Add a helper to read the sequence lock of a time namespace aware...
authorThomas Weißschuh <thomas.weissschuh@linutronix.de>
Fri, 27 Feb 2026 06:43:21 +0000 (07:43 +0100)
committerThomas Gleixner <tglx@kernel.org>
Wed, 11 Mar 2026 09:27:35 +0000 (10:27 +0100)
Currently there are three different open-coded variants of a time
namespace aware variant of vdso_read_begin(). They make the code hard to
read and introduce an inconsistency, as only the first copy uses
unlikely().

Split the code into a shared helper function.
Move that next to the definition of the regular vdso_read_begin(), so
that any future changes can be kept in sync easily.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260227-vdso-cleanups-v1-2-c848b4bc4850@linutronix.de
include/vdso/helpers.h
lib/vdso/gettimeofday.c

index 1a5ee9d9052c38553c0cdf413e0030286f884d53..9ccf6b53ef508c206eeac5ff50974fdcab23c335 100644 (file)
@@ -18,6 +18,28 @@ static __always_inline u32 vdso_read_begin(const struct vdso_clock *vc)
        return seq;
 }
 
+/*
+ * Variant of vdso_read_begin() to handle VDSO_CLOCKMODE_TIMENS.
+ *
+ * Time namespace enabled tasks have a special VVAR page installed which has
+ * vc->seq set to 1 and vc->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non
+ * time namespace affected tasks this does not affect performance because if
+ * vc->seq is odd, i.e. a concurrent update is in progress the extra check for
+ * vc->clock_mode is just a few extra instructions while spin waiting for
+ * vc->seq to become even again.
+ */
+static __always_inline bool vdso_read_begin_timens(const struct vdso_clock *vc, u32 *seq)
+{
+       while (unlikely((*seq = READ_ONCE(vc->seq)) & 1)) {
+               if (IS_ENABLED(CONFIG_TIME_NS) && vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
+                       return true;
+               cpu_relax();
+       }
+       smp_rmb();
+
+       return false;
+}
+
 static __always_inline u32 vdso_read_retry(const struct vdso_clock *vc,
                                           u32 start)
 {
index 4939ee86af653af5f3e3b761c55f826e39cf76eb..e493696769288dee866489f6021db13a33c8f343 100644 (file)
@@ -158,24 +158,8 @@ bool do_hres(const struct vdso_time_data *vd, const struct vdso_clock *vc,
                return false;
 
        do {
-               /*
-                * Open coded function vdso_read_begin() to handle
-                * VDSO_CLOCKMODE_TIMENS. Time namespace enabled tasks have a
-                * special VVAR page installed which has vc->seq set to 1 and
-                * vc->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time
-                * namespace affected tasks this does not affect performance
-                * because if vc->seq is odd, i.e. a concurrent update is in
-                * progress the extra check for vc->clock_mode is just a few
-                * extra instructions while spin waiting for vc->seq to become
-                * even again.
-                */
-               while (unlikely((seq = READ_ONCE(vc->seq)) & 1)) {
-                       if (IS_ENABLED(CONFIG_TIME_NS) &&
-                           vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
-                               return do_hres_timens(vd, vc, clk, ts);
-                       cpu_relax();
-               }
-               smp_rmb();
+               if (vdso_read_begin_timens(vc, &seq))
+                       return do_hres_timens(vd, vc, clk, ts);
 
                if (!vdso_get_timestamp(vd, vc, clk, &sec, &ns))
                        return false;
@@ -223,17 +207,8 @@ bool do_coarse(const struct vdso_time_data *vd, const struct vdso_clock *vc,
        u32 seq;
 
        do {
-               /*
-                * Open coded function vdso_read_begin() to handle
-                * VDSO_CLOCK_TIMENS. See comment in do_hres().
-                */
-               while ((seq = READ_ONCE(vc->seq)) & 1) {
-                       if (IS_ENABLED(CONFIG_TIME_NS) &&
-                           vc->clock_mode == VDSO_CLOCKMODE_TIMENS)
-                               return do_coarse_timens(vd, vc, clk, ts);
-                       cpu_relax();
-               }
-               smp_rmb();
+               if (vdso_read_begin_timens(vc, &seq))
+                       return do_coarse_timens(vd, vc, clk, ts);
 
                ts->tv_sec = vdso_ts->sec;
                ts->tv_nsec = vdso_ts->nsec;
@@ -256,20 +231,12 @@ bool do_aux(const struct vdso_time_data *vd, clockid_t clock, struct __kernel_ti
        vc = &vd->aux_clock_data[idx];
 
        do {
-               /*
-                * Open coded function vdso_read_begin() to handle
-                * VDSO_CLOCK_TIMENS. See comment in do_hres().
-                */
-               while ((seq = READ_ONCE(vc->seq)) & 1) {
-                       if (IS_ENABLED(CONFIG_TIME_NS) && vc->clock_mode == VDSO_CLOCKMODE_TIMENS) {
-                               vd = __arch_get_vdso_u_timens_data(vd);
-                               vc = &vd->aux_clock_data[idx];
-                               /* Re-read from the real time data page */
-                               continue;
-                       }
-                       cpu_relax();
+               if (vdso_read_begin_timens(vc, &seq)) {
+                       vd = __arch_get_vdso_u_timens_data(vd);
+                       vc = &vd->aux_clock_data[idx];
+                       /* Re-read from the real time data page */
+                       continue;
                }
-               smp_rmb();
 
                /* Auxclock disabled? */
                if (vc->clock_mode == VDSO_CLOCKMODE_NONE)