Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vdso/gettimeofday: Add a helper to read the sequence lock of a time namespace aware clock

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

authored by

Thomas Weißschuh and committed by
Thomas Gleixner
ed78b7b2 08cd5e1d

+31 -42
+22
include/vdso/helpers.h
··· 18 18 return seq; 19 19 } 20 20 21 + /* 22 + * Variant of vdso_read_begin() to handle VDSO_CLOCKMODE_TIMENS. 23 + * 24 + * Time namespace enabled tasks have a special VVAR page installed which has 25 + * vc->seq set to 1 and vc->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non 26 + * time namespace affected tasks this does not affect performance because if 27 + * vc->seq is odd, i.e. a concurrent update is in progress the extra check for 28 + * vc->clock_mode is just a few extra instructions while spin waiting for 29 + * vc->seq to become even again. 30 + */ 31 + static __always_inline bool vdso_read_begin_timens(const struct vdso_clock *vc, u32 *seq) 32 + { 33 + while (unlikely((*seq = READ_ONCE(vc->seq)) & 1)) { 34 + if (IS_ENABLED(CONFIG_TIME_NS) && vc->clock_mode == VDSO_CLOCKMODE_TIMENS) 35 + return true; 36 + cpu_relax(); 37 + } 38 + smp_rmb(); 39 + 40 + return false; 41 + } 42 + 21 43 static __always_inline u32 vdso_read_retry(const struct vdso_clock *vc, 22 44 u32 start) 23 45 {
+9 -42
lib/vdso/gettimeofday.c
··· 158 158 return false; 159 159 160 160 do { 161 - /* 162 - * Open coded function vdso_read_begin() to handle 163 - * VDSO_CLOCKMODE_TIMENS. Time namespace enabled tasks have a 164 - * special VVAR page installed which has vc->seq set to 1 and 165 - * vc->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time 166 - * namespace affected tasks this does not affect performance 167 - * because if vc->seq is odd, i.e. a concurrent update is in 168 - * progress the extra check for vc->clock_mode is just a few 169 - * extra instructions while spin waiting for vc->seq to become 170 - * even again. 171 - */ 172 - while (unlikely((seq = READ_ONCE(vc->seq)) & 1)) { 173 - if (IS_ENABLED(CONFIG_TIME_NS) && 174 - vc->clock_mode == VDSO_CLOCKMODE_TIMENS) 175 - return do_hres_timens(vd, vc, clk, ts); 176 - cpu_relax(); 177 - } 178 - smp_rmb(); 161 + if (vdso_read_begin_timens(vc, &seq)) 162 + return do_hres_timens(vd, vc, clk, ts); 179 163 180 164 if (!vdso_get_timestamp(vd, vc, clk, &sec, &ns)) 181 165 return false; ··· 207 223 u32 seq; 208 224 209 225 do { 210 - /* 211 - * Open coded function vdso_read_begin() to handle 212 - * VDSO_CLOCK_TIMENS. See comment in do_hres(). 213 - */ 214 - while ((seq = READ_ONCE(vc->seq)) & 1) { 215 - if (IS_ENABLED(CONFIG_TIME_NS) && 216 - vc->clock_mode == VDSO_CLOCKMODE_TIMENS) 217 - return do_coarse_timens(vd, vc, clk, ts); 218 - cpu_relax(); 219 - } 220 - smp_rmb(); 226 + if (vdso_read_begin_timens(vc, &seq)) 227 + return do_coarse_timens(vd, vc, clk, ts); 221 228 222 229 ts->tv_sec = vdso_ts->sec; 223 230 ts->tv_nsec = vdso_ts->nsec; ··· 231 256 vc = &vd->aux_clock_data[idx]; 232 257 233 258 do { 234 - /* 235 - * Open coded function vdso_read_begin() to handle 236 - * VDSO_CLOCK_TIMENS. See comment in do_hres(). 237 - */ 238 - while ((seq = READ_ONCE(vc->seq)) & 1) { 239 - if (IS_ENABLED(CONFIG_TIME_NS) && vc->clock_mode == VDSO_CLOCKMODE_TIMENS) { 240 - vd = __arch_get_vdso_u_timens_data(vd); 241 - vc = &vd->aux_clock_data[idx]; 242 - /* Re-read from the real time data page */ 243 - continue; 244 - } 245 - cpu_relax(); 259 + if (vdso_read_begin_timens(vc, &seq)) { 260 + vd = __arch_get_vdso_u_timens_data(vd); 261 + vc = &vd->aux_clock_data[idx]; 262 + /* Re-read from the real time data page */ 263 + continue; 246 264 } 247 - smp_rmb(); 248 265 249 266 /* Auxclock disabled? */ 250 267 if (vc->clock_mode == VDSO_CLOCKMODE_NONE)