1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
4 */
5
6 #include <time.h>
7
8 #define TST_NO_DEFAULT_MAIN
9 #include "tst_test.h"
10 #include "tst_timer.h"
11 #include "tst_clocks.h"
12 #include "lapi/syscalls.h"
13 #include "lapi/posix_clocks.h"
14
15 typedef int (*mysyscall)(clockid_t clk_id, void *ts);
16
syscall_supported_by_kernel(long sysnr)17 int syscall_supported_by_kernel(long sysnr)
18 {
19 int ret;
20 struct timespec foo;
21
22 ret = syscall(sysnr, 0, &foo);
23 if (ret == -1 && errno == ENOSYS)
24 return 0;
25
26 return 1;
27 }
28
tst_clock_getres(clockid_t clk_id,struct timespec * res)29 int tst_clock_getres(clockid_t clk_id, struct timespec *res)
30 {
31 static struct tst_ts tts = { 0, };
32 static mysyscall func;
33 int ret;
34
35 #if (__NR_clock_getres_time64 != __LTP__NR_INVALID_SYSCALL)
36 if (!func && syscall_supported_by_kernel(__NR_clock_getres_time64)) {
37 func = sys_clock_getres64;
38 tts.type = TST_KERN_TIMESPEC;
39 }
40 #endif
41
42 if (!func && syscall_supported_by_kernel(__NR_clock_getres)) {
43 func = sys_clock_getres;
44 tts.type = TST_KERN_OLD_TIMESPEC;
45 }
46
47 if (!func) {
48 tst_res(TCONF, "clock_getres() not available");
49 errno = ENOSYS;
50 return -1;
51 }
52
53 ret = func(clk_id, tst_ts_get(&tts));
54 res->tv_sec = tst_ts_get_sec(tts);
55 res->tv_nsec = tst_ts_get_nsec(tts);
56 return ret;
57 }
58
tst_clock_gettime(clockid_t clk_id,struct timespec * ts)59 int tst_clock_gettime(clockid_t clk_id, struct timespec *ts)
60 {
61 static struct tst_ts tts = { 0, };
62 static mysyscall func;
63 int ret;
64
65 #if (__NR_clock_gettime64 != __LTP__NR_INVALID_SYSCALL)
66 if (!func && syscall_supported_by_kernel(__NR_clock_gettime64)) {
67 func = sys_clock_gettime64;
68 tts.type = TST_KERN_TIMESPEC;
69 }
70 #endif
71
72 if (!func && syscall_supported_by_kernel(__NR_clock_gettime)) {
73 func = sys_clock_gettime;
74 tts.type = TST_KERN_OLD_TIMESPEC;
75 }
76
77 if (!func) {
78 tst_res(TCONF, "clock_gettime() not available");
79 errno = ENOSYS;
80 return -1;
81 }
82
83 ret = func(clk_id, tst_ts_get(&tts));
84 ts->tv_sec = tst_ts_get_sec(tts);
85 ts->tv_nsec = tst_ts_get_nsec(tts);
86 return ret;
87 }
88
tst_clock_settime(clockid_t clk_id,struct timespec * ts)89 int tst_clock_settime(clockid_t clk_id, struct timespec *ts)
90 {
91 static struct tst_ts tts = { 0, };
92 static mysyscall func;
93
94 #if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
95 if (!func && syscall_supported_by_kernel(__NR_clock_settime64)) {
96 func = sys_clock_settime64;
97 tts.type = TST_KERN_TIMESPEC;
98 }
99 #endif
100
101 if (!func && syscall_supported_by_kernel(__NR_clock_settime)) {
102 func = sys_clock_settime;
103 tts.type = TST_KERN_OLD_TIMESPEC;
104 }
105
106 if (!func) {
107 tst_res(TCONF, "clock_settime() not available");
108 errno = ENOSYS;
109 return -1;
110 }
111
112 tst_ts_set_sec(&tts, ts->tv_sec);
113 tst_ts_set_nsec(&tts, ts->tv_nsec);
114 return func(clk_id, tst_ts_get(&tts));
115 }
116
tst_clock_name(clockid_t clk_id)117 const char *tst_clock_name(clockid_t clk_id)
118 {
119 switch (clk_id) {
120 case CLOCK_REALTIME:
121 return "CLOCK_REALTIME";
122 case CLOCK_MONOTONIC:
123 return "CLOCK_MONOTONIC";
124 case CLOCK_PROCESS_CPUTIME_ID:
125 return "CLOCK_PROCESS_CPUTIME_ID";
126 case CLOCK_THREAD_CPUTIME_ID:
127 return "CLOCK_THREAD_CPUTIME_ID";
128 case CLOCK_MONOTONIC_RAW:
129 return "CLOCK_MONOTONIC_RAW";
130 case CLOCK_REALTIME_COARSE:
131 return "CLOCK_REALTIME_COARSE";
132 case CLOCK_MONOTONIC_COARSE:
133 return "CLOCK_MONOTONIC_COARSE";
134 case CLOCK_BOOTTIME:
135 return "CLOCK_BOOTTIME";
136 case CLOCK_REALTIME_ALARM:
137 return "CLOCK_REALTIME_ALARM";
138 case CLOCK_BOOTTIME_ALARM:
139 return "CLOCK_BOOTTIME_ALARM";
140 case CLOCK_TAI:
141 return "CLOCK_TAI";
142 default:
143 return "INVALID/UNKNOWN CLOCK";
144 }
145 }
146
tst_get_fs_timestamp(void)147 time_t tst_get_fs_timestamp(void)
148 {
149 struct timespec ts;
150 int ret;
151
152 ret = tst_clock_gettime(CLOCK_REALTIME_COARSE, &ts);
153
154 if (ret < 0)
155 tst_brk(TBROK | TERRNO, "clock_gettime(CLOCK_REALTIME_COARSE)");
156
157 return ts.tv_sec;
158 }
159