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