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; 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