// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2019 Linaro Limited. All rights reserved. * Author: Rafael David Tinoco */ #include #define TST_NO_DEFAULT_MAIN #include "tst_test.h" #include "tst_timer.h" #include "tst_clocks.h" #include "tst_rtctime.h" #include "tst_wallclock.h" #include "lapi/posix_clocks.h" static struct timespec real_begin, mono_begin; static struct rtc_time rtc_begin; static int clock_saved; void tst_wallclock_save(void) { /* save initial monotonic time to restore it when needed */ if (tst_clock_gettime(CLOCK_REALTIME, &real_begin)) tst_brk(TBROK | TERRNO, "tst_clock_gettime() realtime failed"); if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_begin)) { if (errno == EINVAL) { tst_brk(TCONF | TERRNO, "tst_clock_gettime() didn't support CLOCK_MONOTONIC_RAW"); } tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed"); } clock_saved = 1; } void tst_wallclock_restore(void) { static struct timespec mono_end, elapsed, adjust; if (!clock_saved) return; clock_saved = 0; if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_end)) tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed"); elapsed = tst_timespec_diff(mono_end, mono_begin); adjust = tst_timespec_add(real_begin, elapsed); /* restore realtime clock based on monotonic delta */ if (tst_clock_settime(CLOCK_REALTIME, &adjust)) tst_brk(TBROK | TERRNO, "tst_clock_settime() realtime failed"); } void tst_rtc_clock_save(const char *rtc_dev) { /* save initial monotonic time to restore it when needed */ if (tst_rtc_gettime(rtc_dev, &rtc_begin)) tst_brk(TBROK | TERRNO, "tst_rtc_gettime() realtime failed"); if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_begin)) tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed"); clock_saved = 1; } void tst_rtc_clock_restore(const char *rtc_dev) { static struct timespec mono_end, elapsed; static struct timespec rtc_begin_tm, rtc_adjust; static struct rtc_time rtc_restore; if (!clock_saved) return; clock_saved = 0; if (tst_clock_gettime(CLOCK_MONOTONIC_RAW, &mono_end)) tst_brk(TBROK | TERRNO, "tst_clock_gettime() monotonic failed"); elapsed = tst_timespec_diff(mono_end, mono_begin); rtc_begin_tm.tv_nsec = 0; rtc_begin_tm.tv_sec = tst_rtc_tm_to_time(&rtc_begin); rtc_adjust = tst_timespec_add(rtc_begin_tm, elapsed); tst_rtc_time_to_tm(rtc_adjust.tv_sec, &rtc_restore); /* restore realtime clock based on monotonic delta */ if (tst_rtc_settime(rtc_dev, &rtc_restore)) tst_brk(TBROK | TERRNO, "tst_rtc_settime() realtime failed"); }