22/*
33 * Generic userspace implementations of gettimeofday() and similar.
44 */
5+ #include <vdso/auxclock.h>
56#include <vdso/datapage.h>
67#include <vdso/helpers.h>
78
@@ -74,7 +75,7 @@ static inline bool vdso_cycles_ok(u64 cycles)
7475static __always_inline bool vdso_clockid_valid (clockid_t clock )
7576{
7677 /* Check for negative values or invalid clocks */
77- return likely ((u32 ) clock < MAX_CLOCKS );
78+ return likely ((u32 ) clock <= CLOCK_AUX_LAST );
7879}
7980
8081/*
@@ -268,6 +269,48 @@ bool do_coarse(const struct vdso_time_data *vd, const struct vdso_clock *vc,
268269 return true;
269270}
270271
272+ static __always_inline
273+ bool do_aux (const struct vdso_time_data * vd , clockid_t clock , struct __kernel_timespec * ts )
274+ {
275+ const struct vdso_clock * vc ;
276+ u32 seq , idx ;
277+ u64 sec , ns ;
278+
279+ if (!IS_ENABLED (CONFIG_POSIX_AUX_CLOCKS ))
280+ return false;
281+
282+ idx = clock - CLOCK_AUX ;
283+ vc = & vd -> aux_clock_data [idx ];
284+
285+ do {
286+ /*
287+ * Open coded function vdso_read_begin() to handle
288+ * VDSO_CLOCK_TIMENS. See comment in do_hres().
289+ */
290+ while ((seq = READ_ONCE (vc -> seq )) & 1 ) {
291+ if (IS_ENABLED (CONFIG_TIME_NS ) && vc -> clock_mode == VDSO_CLOCKMODE_TIMENS ) {
292+ vd = __arch_get_vdso_u_timens_data (vd );
293+ vc = & vd -> aux_clock_data [idx ];
294+ /* Re-read from the real time data page */
295+ continue ;
296+ }
297+ cpu_relax ();
298+ }
299+ smp_rmb ();
300+
301+ /* Auxclock disabled? */
302+ if (vc -> clock_mode == VDSO_CLOCKMODE_NONE )
303+ return false;
304+
305+ if (!vdso_get_timestamp (vd , vc , VDSO_BASE_AUX , & sec , & ns ))
306+ return false;
307+ } while (unlikely (vdso_read_retry (vc , seq )));
308+
309+ vdso_set_timespec (ts , sec , ns );
310+
311+ return true;
312+ }
313+
271314static __always_inline bool
272315__cvdso_clock_gettime_common (const struct vdso_time_data * vd , clockid_t clock ,
273316 struct __kernel_timespec * ts )
@@ -289,6 +332,8 @@ __cvdso_clock_gettime_common(const struct vdso_time_data *vd, clockid_t clock,
289332 return do_coarse (vd , & vc [CS_HRES_COARSE ], clock , ts );
290333 else if (msk & VDSO_RAW )
291334 vc = & vc [CS_RAW ];
335+ else if (msk & VDSO_AUX )
336+ return do_aux (vd , clock , ts );
292337 else
293338 return false;
294339
@@ -433,6 +478,8 @@ bool __cvdso_clock_getres_common(const struct vdso_time_data *vd, clockid_t cloc
433478 * Preserves the behaviour of posix_get_coarse_res().
434479 */
435480 ns = LOW_RES_NSEC ;
481+ } else if (msk & VDSO_AUX ) {
482+ ns = aux_clock_resolution_ns ();
436483 } else {
437484 return false;
438485 }
0 commit comments