• 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 #include <errno.h>
8 
9 #define TST_NO_DEFAULT_MAIN
10 
11 #include "tst_test.h"
12 #include "tst_timer.h"
13 #include "tst_clocks.h"
14 #include "tst_rtctime.h"
15 #include "tst_wallclock.h"
16 #include "lapi/posix_clocks.h"
17 
18 static struct timespec real_begin, mono_begin;
19 
20 static struct rtc_time rtc_begin;
21 
22 static int clock_saved;
23 
tst_wallclock_save(void)24 void tst_wallclock_save(void)
25 {
26 	/* save initial monotonic time to restore it when needed */
27 
28 	if (tst_clock_gettime(CLOCK_REALTIME, &real_begin))
29 		tst_brk(TBROK | TERRNO, "tst_clock_gettime() realtime failed");
30 
31 	if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_begin)) {
32 		if (errno == EINVAL) {
33 			tst_brk(TCONF | TERRNO,
34 				"tst_clock_gettime() didn't support CLOCK_MONOTONIC_RAW");
35 		}
36 
37 		tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed");
38 	}
39 
40 	clock_saved = 1;
41 }
42 
tst_wallclock_restore(void)43 void tst_wallclock_restore(void)
44 {
45 	static struct timespec mono_end, elapsed, adjust;
46 
47 	if (!clock_saved)
48 		return;
49 
50 	clock_saved = 0;
51 
52 	if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_end))
53 		tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed");
54 
55 	elapsed = tst_timespec_diff(mono_end, mono_begin);
56 
57 	adjust = tst_timespec_add(real_begin, elapsed);
58 
59 	/* restore realtime clock based on monotonic delta */
60 
61 	if (tst_clock_settime(CLOCK_REALTIME, &adjust))
62 		tst_brk(TBROK | TERRNO, "tst_clock_settime() realtime failed");
63 }
64 
tst_rtc_clock_save(const char * rtc_dev)65 void tst_rtc_clock_save(const char *rtc_dev)
66 {
67 	/* save initial monotonic time to restore it when needed */
68 	if (tst_rtc_gettime(rtc_dev, &rtc_begin))
69 		tst_brk(TBROK | TERRNO, "tst_rtc_gettime() realtime failed");
70 
71 	if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_begin))
72 		tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed");
73 
74 	clock_saved = 1;
75 }
76 
tst_rtc_clock_restore(const char * rtc_dev)77 void tst_rtc_clock_restore(const char *rtc_dev)
78 {
79 	static struct timespec mono_end, elapsed;
80 	static struct timespec rtc_begin_tm, rtc_adjust;
81 	static struct rtc_time rtc_restore;
82 
83 	if (!clock_saved)
84 		return;
85 
86 	clock_saved = 0;
87 
88 	if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_end))
89 		tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed");
90 
91 	elapsed = tst_timespec_diff(mono_end, mono_begin);
92 
93 	rtc_begin_tm.tv_nsec = 0;
94 	rtc_begin_tm.tv_sec = tst_rtc_tm_to_time(&rtc_begin);
95 
96 	rtc_adjust = tst_timespec_add(rtc_begin_tm, elapsed);
97 
98 	tst_rtc_time_to_tm(rtc_adjust.tv_sec, &rtc_restore);
99 
100 	/* restore realtime clock based on monotonic delta */
101 	if (tst_rtc_settime(rtc_dev, &rtc_restore))
102 		tst_brk(TBROK | TERRNO, "tst_rtc_settime() realtime failed");
103 }
104