summaryrefslogtreecommitdiffstats
path: root/src/kernel/tests/lib/tst_clocks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/tests/lib/tst_clocks.c')
-rw-r--r--src/kernel/tests/lib/tst_clocks.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/kernel/tests/lib/tst_clocks.c b/src/kernel/tests/lib/tst_clocks.c
new file mode 100644
index 0000000..cdcb9fc
--- /dev/null
+++ b/src/kernel/tests/lib/tst_clocks.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#include <time.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_timer.h"
+#include "tst_clocks.h"
+#include "lapi/syscalls.h"
+#include "lapi/posix_clocks.h"
+
+typedef int (*mysyscall)(clockid_t clk_id, void *ts);
+
+int syscall_supported_by_kernel(long sysnr)
+{
+ int ret;
+
+ ret = syscall(sysnr, 0, NULL);
+ if (ret == -1 && errno == ENOSYS)
+ return 0;
+
+ return 1;
+}
+
+int tst_clock_getres(clockid_t clk_id, struct timespec *res)
+{
+ static struct tst_ts tts = { 0, };
+ static mysyscall func;
+ int ret;
+
+#if (__NR_clock_getres_time64 != __LTP__NR_INVALID_SYSCALL)
+ if (!func && syscall_supported_by_kernel(__NR_clock_getres_time64)) {
+ func = sys_clock_getres64;
+ tts.type = TST_KERN_TIMESPEC;
+ }
+#endif
+
+ if (!func && syscall_supported_by_kernel(__NR_clock_getres)) {
+ func = sys_clock_getres;
+ tts.type = TST_KERN_OLD_TIMESPEC;
+ }
+
+ if (!func) {
+ tst_res(TCONF, "clock_getres() not available");
+ errno = ENOSYS;
+ return -1;
+ }
+
+ ret = func(clk_id, tst_ts_get(&tts));
+ res->tv_sec = tst_ts_get_sec(tts);
+ res->tv_nsec = tst_ts_get_nsec(tts);
+ return ret;
+}
+
+int tst_clock_gettime(clockid_t clk_id, struct timespec *ts)
+{
+ static struct tst_ts tts = { 0, };
+ static mysyscall func;
+ int ret;
+
+#if (__NR_clock_gettime64 != __LTP__NR_INVALID_SYSCALL)
+ if (!func && syscall_supported_by_kernel(__NR_clock_gettime64)) {
+ func = sys_clock_gettime64;
+ tts.type = TST_KERN_TIMESPEC;
+ }
+#endif
+
+ if (!func && syscall_supported_by_kernel(__NR_clock_gettime)) {
+ func = sys_clock_gettime;
+ tts.type = TST_KERN_OLD_TIMESPEC;
+ }
+
+ if (!func) {
+ tst_res(TCONF, "clock_gettime() not available");
+ errno = ENOSYS;
+ return -1;
+ }
+
+ ret = func(clk_id, tst_ts_get(&tts));
+ ts->tv_sec = tst_ts_get_sec(tts);
+ ts->tv_nsec = tst_ts_get_nsec(tts);
+ return ret;
+}
+
+int tst_clock_settime(clockid_t clk_id, struct timespec *ts)
+{
+ static struct tst_ts tts = { 0, };
+ static mysyscall func;
+
+#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL)
+ if (!func && syscall_supported_by_kernel(__NR_clock_settime64)) {
+ func = sys_clock_settime64;
+ tts.type = TST_KERN_TIMESPEC;
+ }
+#endif
+
+ if (!func && syscall_supported_by_kernel(__NR_clock_settime)) {
+ func = sys_clock_settime;
+ tts.type = TST_KERN_OLD_TIMESPEC;
+ }
+
+ if (!func) {
+ tst_res(TCONF, "clock_settime() not available");
+ errno = ENOSYS;
+ return -1;
+ }
+
+ tst_ts_set_sec(&tts, ts->tv_sec);
+ tst_ts_set_nsec(&tts, ts->tv_nsec);
+ return func(clk_id, tst_ts_get(&tts));
+}
+
+const char *tst_clock_name(clockid_t clk_id)
+{
+ switch (clk_id) {
+ case CLOCK_REALTIME:
+ return "CLOCK_REALTIME";
+ case CLOCK_MONOTONIC:
+ return "CLOCK_MONOTONIC";
+ case CLOCK_PROCESS_CPUTIME_ID:
+ return "CLOCK_PROCESS_CPUTIME_ID";
+ case CLOCK_THREAD_CPUTIME_ID:
+ return "CLOCK_THREAD_CPUTIME_ID";
+ case CLOCK_MONOTONIC_RAW:
+ return "CLOCK_MONOTONIC_RAW";
+ case CLOCK_REALTIME_COARSE:
+ return "CLOCK_REALTIME_COARSE";
+ case CLOCK_MONOTONIC_COARSE:
+ return "CLOCK_MONOTONIC_COARSE";
+ case CLOCK_BOOTTIME:
+ return "CLOCK_BOOTTIME";
+ case CLOCK_REALTIME_ALARM:
+ return "CLOCK_REALTIME_ALARM";
+ case CLOCK_BOOTTIME_ALARM:
+ return "CLOCK_BOOTTIME_ALARM";
+ case CLOCK_TAI:
+ return "CLOCK_TAI";
+ default:
+ return "INVALID/UNKNOWN CLOCK";
+ }
+}