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 | |
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 | */ |
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 | |
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 | |