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
syscall_clock_getres(clockid_t _clkid,struct timespec * _ts)30 static 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
39 const 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 */
vdso_test_clock(unsigned int clock_id)68 static 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
main(int argc,char ** argv)85 int 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