Skip to content

Commit cd3557a

Browse files
t-8chKAGA-KOKO
authored andcommitted
vdso/gettimeofday: Add support for auxiliary clocks
Expose the auxiliary clocks through the vDSO. Architectures not using the generic vDSO time framework, namely SPARC64, are not supported. Signed-off-by: Thomas Weißschuh <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 380b84e commit cd3557a

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

include/vdso/datapage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef __ASSEMBLY__
66

77
#include <linux/compiler.h>
8+
#include <uapi/linux/bits.h>
89
#include <uapi/linux/time.h>
910
#include <uapi/linux/types.h>
1011
#include <uapi/asm-generic/errno-base.h>
@@ -46,6 +47,7 @@ struct vdso_arch_data {
4647
#define VDSO_COARSE (BIT(CLOCK_REALTIME_COARSE) | \
4748
BIT(CLOCK_MONOTONIC_COARSE))
4849
#define VDSO_RAW (BIT(CLOCK_MONOTONIC_RAW))
50+
#define VDSO_AUX __GENMASK(CLOCK_AUX_LAST, CLOCK_AUX)
4951

5052
#define CS_HRES_COARSE 0
5153
#define CS_RAW 1

lib/vdso/gettimeofday.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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)
7475
static __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+
271314
static __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

Comments
 (0)