1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 Linaro Limited. All rights reserved.
4 * Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
5 */
6 /*
7 * Basic test for clock_gettime(2) on multiple clocks:
8 *
9 * 1) CLOCK_REALTIME
10 * 2) CLOCK_MONOTONIC
11 * 3) CLOCK_PROCESS_CPUTIME_ID
12 * 4) CLOCK_THREAD_CPUTIME_ID
13 * 5) CLOCK_REALTIME_COARSE
14 * 6) CLOCK_MONOTONIC_COARSE
15 * 7) CLOCK_MONOTONIC_RAW
16 * 8) CLOCK_BOOTTIME
17 */
18
19 #include "config.h"
20 #include "time64_variants.h"
21 #include "tst_timer.h"
22 #include "tst_safe_clocks.h"
23
24 struct test_case {
25 clockid_t clktype;
26 int allow_inval;
27 };
28
29 static struct test_case tc[] = {
30 {
31 .clktype = CLOCK_REALTIME,
32 },
33 {
34 .clktype = CLOCK_MONOTONIC,
35 },
36 {
37 .clktype = CLOCK_PROCESS_CPUTIME_ID,
38 },
39 {
40 .clktype = CLOCK_THREAD_CPUTIME_ID,
41 },
42 {
43 .clktype = CLOCK_REALTIME_COARSE,
44 .allow_inval = 1,
45 },
46 {
47 .clktype = CLOCK_MONOTONIC_COARSE,
48 .allow_inval = 1,
49 },
50 {
51 .clktype = CLOCK_MONOTONIC_RAW,
52 .allow_inval = 1,
53 },
54 {
55 .clktype = CLOCK_BOOTTIME,
56 .allow_inval = 1,
57 },
58 };
59
60 static struct tst_ts spec;
61
62 static struct time64_variants variants[] = {
63 { .clock_gettime = libc_clock_gettime, .ts_type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
64
65 #if (__NR_clock_gettime != __LTP__NR_INVALID_SYSCALL)
66 { .clock_gettime = sys_clock_gettime, .ts_type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
67 #endif
68
69 #if (__NR_clock_gettime64 != __LTP__NR_INVALID_SYSCALL)
70 { .clock_gettime = sys_clock_gettime64, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
71 #endif
72 };
73
setup(void)74 static void setup(void)
75 {
76 tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
77 }
78
verify_clock_gettime(unsigned int i)79 static void verify_clock_gettime(unsigned int i)
80 {
81 struct time64_variants *tv = &variants[tst_variant];
82 int ret;
83
84 memset(&spec, 0, sizeof(spec));
85 spec.type = tv->ts_type;
86
87 TEST(tv->clock_gettime(tc[i].clktype, tst_ts_get(&spec)));
88
89 if (TST_RET == -1) {
90 /* errors: allow unsupported clock types */
91 if (tc[i].allow_inval && TST_ERR == EINVAL) {
92 tst_res(TPASS, "clock_gettime(2): unsupported clock %s failed as expected",
93 tst_clock_name(tc[i].clktype));
94 } else {
95 tst_res(TFAIL | TTERRNO, "clock_gettime(2): clock %s failed unexpectedly",
96 tst_clock_name(tc[i].clktype));
97 }
98
99 } else {
100 /* success: also check if timespec was changed */
101 ret = tst_ts_valid(&spec);
102 if (!ret) {
103 tst_res(TPASS, "clock_gettime(2): clock %s passed",
104 tst_clock_name(tc[i].clktype));
105 } else if (ret == -1) {
106 tst_res(TFAIL, "clock_gettime(2): clock %s passed, unchanged timespec",
107 tst_clock_name(tc[i].clktype));
108 } else if (ret == -2) {
109 tst_res(TFAIL, "clock_gettime(2): clock %s passed, Corrupted timespec",
110 tst_clock_name(tc[i].clktype));
111 }
112 }
113 }
114
115 static struct tst_test test = {
116 .test = verify_clock_gettime,
117 .tcnt = ARRAY_SIZE(tc),
118 .test_variants = ARRAY_SIZE(variants),
119 .setup = setup,
120 .needs_root = 1,
121 };
122