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