1// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2/*
3 * vdso_clock_getres.c: Sample code to test clock_getres.
4 * Copyright (c) 2019 Arm Ltd.
5 *
6 * Compile with:
7 * gcc -std=gnu99 vdso_clock_getres.c
8 *
9 * Tested on ARM, ARM64, MIPS32, x86 (32-bit and 64-bit),
10 * Power (32-bit and 64-bit), S390x (32-bit and 64-bit).
11 * Might work on other architectures.
12 */
13
14#define _GNU_SOURCE
15#include <elf.h>
16#include <err.h>
17#include <fcntl.h>
18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <time.h>
22#include <sys/auxv.h>
23#include <sys/mman.h>
24#include <sys/time.h>
25#include <unistd.h>
26#include <sys/syscall.h>
27
28#include "../kselftest.h"
29
30static long syscall_clock_getres(clockid_t _clkid, struct timespec *_ts)
31{
32 long ret;
33
34 ret = syscall(SYS_clock_getres, _clkid, _ts);
35
36 return ret;
37}
38
39const char *vdso_clock_name[12] = {
40 "CLOCK_REALTIME",
41 "CLOCK_MONOTONIC",
42 "CLOCK_PROCESS_CPUTIME_ID",
43 "CLOCK_THREAD_CPUTIME_ID",
44 "CLOCK_MONOTONIC_RAW",
45 "CLOCK_REALTIME_COARSE",
46 "CLOCK_MONOTONIC_COARSE",
47 "CLOCK_BOOTTIME",
48 "CLOCK_REALTIME_ALARM",
49 "CLOCK_BOOTTIME_ALARM",
50 "CLOCK_SGI_CYCLE",
51 "CLOCK_TAI",
52};
53
54/*
55 * This function calls clock_getres in vdso and by system call
56 * with different values for clock_id.
57 *
58 * Example of output:
59 *
60 * clock_id: CLOCK_REALTIME [PASS]
61 * clock_id: CLOCK_BOOTTIME [PASS]
62 * clock_id: CLOCK_TAI [PASS]
63 * clock_id: CLOCK_REALTIME_COARSE [PASS]
64 * clock_id: CLOCK_MONOTONIC [PASS]
65 * clock_id: CLOCK_MONOTONIC_RAW [PASS]
66 * clock_id: CLOCK_MONOTONIC_COARSE [PASS]
67 */
68static inline int vdso_test_clock(unsigned int clock_id)
69{
70 struct timespec x, y;
71
72 printf("clock_id: %s", vdso_clock_name[clock_id]);
73 clock_getres(clock_id, &x);
74 syscall_clock_getres(clock_id, &y);
75
76 if ((x.tv_sec != y.tv_sec) || (x.tv_nsec != y.tv_nsec)) {
77 printf(" [FAIL]\n");
78 return KSFT_FAIL;
79 }
80
81 printf(" [PASS]\n");
82 return KSFT_PASS;
83}
84
85int main(int argc, char **argv)
86{
87 int ret = 0;
88
89#if _POSIX_TIMERS > 0
90
91#ifdef CLOCK_REALTIME
92 ret += vdso_test_clock(CLOCK_REALTIME);
93#endif
94
95#ifdef CLOCK_BOOTTIME
96 ret += vdso_test_clock(CLOCK_BOOTTIME);
97#endif
98
99#ifdef CLOCK_TAI
100 ret += vdso_test_clock(CLOCK_TAI);
101#endif
102
103#ifdef CLOCK_REALTIME_COARSE
104 ret += vdso_test_clock(CLOCK_REALTIME_COARSE);
105#endif
106
107#ifdef CLOCK_MONOTONIC
108 ret += vdso_test_clock(CLOCK_MONOTONIC);
109#endif
110
111#ifdef CLOCK_MONOTONIC_RAW
112 ret += vdso_test_clock(CLOCK_MONOTONIC_RAW);
113#endif
114
115#ifdef CLOCK_MONOTONIC_COARSE
116 ret += vdso_test_clock(CLOCK_MONOTONIC_COARSE);
117#endif
118
119#endif
120 if (ret > 0)
121 return KSFT_FAIL;
122
123 return KSFT_PASS;
124}
125

source code of linux/tools/testing/selftests/vDSO/vdso_test_clock_getres.c