• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	long unsigned utime;
77 
78 	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
79 
80 	do {
81 		SAFE_FILE_SCANF("/proc/self/stat",
82 			"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu",
83 			&utime);
84 	} while (utime == 0);
85 }
86 
verify_clock_gettime(unsigned int i)87 static void verify_clock_gettime(unsigned int i)
88 {
89 	struct time64_variants *tv = &variants[tst_variant];
90 	int ret;
91 
92 	memset(&spec, 0, sizeof(spec));
93 	spec.type = tv->ts_type;
94 
95 	TEST(tv->clock_gettime(tc[i].clktype, tst_ts_get(&spec)));
96 
97 	if (TST_RET == -1) {
98 		/* errors: allow unsupported clock types */
99 		if (tc[i].allow_inval && TST_ERR == EINVAL) {
100 			tst_res(TPASS, "clock_gettime(2): unsupported clock %s failed as expected",
101 				tst_clock_name(tc[i].clktype));
102 		} else {
103 			tst_res(TFAIL | TTERRNO, "clock_gettime(2): clock %s failed unexpectedly",
104 				tst_clock_name(tc[i].clktype));
105 		}
106 
107 	} else {
108 		/* success: also check if timespec was changed */
109 		ret = tst_ts_valid(&spec);
110 		if (!ret) {
111 			tst_res(TPASS, "clock_gettime(2): clock %s passed",
112 				tst_clock_name(tc[i].clktype));
113 		} else if (ret == -1) {
114 			tst_res(TFAIL, "clock_gettime(2): clock %s passed, unchanged timespec",
115 				tst_clock_name(tc[i].clktype));
116 		} else if (ret == -2) {
117 			tst_res(TFAIL, "clock_gettime(2): clock %s passed, Corrupted timespec",
118 				tst_clock_name(tc[i].clktype));
119 		}
120 	}
121 }
122 
123 static struct tst_test test = {
124 	.test = verify_clock_gettime,
125 	.tcnt = ARRAY_SIZE(tc),
126 	.test_variants = ARRAY_SIZE(variants),
127 	.setup = setup,
128 	.needs_root = 1,
129 	.timeout = 10,
130 };
131