On 30/04/2026 20:03:13+0800, Wake Liu wrote: > The test case rtc.date_read_loop in rtctest.c fails intermittently because > it checks that the RTC time does not advance by more than 1 second per loop > iteration. However, the loop sleeps for 11ms via nanosleep(), and if the > test thread is descheduled by the OS scheduler (e.g., under heavy system > load in a VM), more than 1 second can elapse between consecutive RTC reads. > This causes the next RTC time read to be 2 or more seconds ahead of the > previous read, triggering a test assertion failure. > > To make the test more resilient against OS scheduling delays, measure the > real elapsed time between iterations using a monotonic clock > (clock_gettime(CLOCK_MONOTONIC)), and compute the actual number of seconds > elapsed (delta_s) between consecutive RTC reads. Then dynamically adjust > the assertion to: > ASSERT_GE(prev_rtc_read + delta_s + 1, rtc_read); > > Signed-off-by: Wake Liu <[email protected]>
Acked-by: Alexandre Belloni <[email protected]> > --- > tools/testing/selftests/rtc/rtctest.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/tools/testing/selftests/rtc/rtctest.c > b/tools/testing/selftests/rtc/rtctest.c > index 8047d9879039..54eb5c255a45 100644 > --- a/tools/testing/selftests/rtc/rtctest.c > +++ b/tools/testing/selftests/rtc/rtctest.c > @@ -116,6 +116,7 @@ TEST_F_TIMEOUT(rtc, date_read_loop, > READ_LOOP_DURATION_SEC + 2) { > long iter_count = 0; > struct rtc_time rtc_tm; > time_t start_rtc_read, prev_rtc_read; > + struct timespec prev_mono, cur_mono; > > if (self->fd == -1 && errno == ENOENT) > SKIP(return, "Skipping test since %s does not exist", rtc_file); > @@ -126,25 +127,31 @@ TEST_F_TIMEOUT(rtc, date_read_loop, > READ_LOOP_DURATION_SEC + 2) { > > rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); > ASSERT_NE(-1, rc); > + clock_gettime(CLOCK_MONOTONIC, &prev_mono); > start_rtc_read = rtc_time_to_timestamp(&rtc_tm); > prev_rtc_read = start_rtc_read; > > do { > time_t rtc_read; > + time_t delta_s = 0; > > rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); > ASSERT_NE(-1, rc); > + clock_gettime(CLOCK_MONOTONIC, &cur_mono); > > rtc_read = rtc_time_to_timestamp(&rtc_tm); > + delta_s = cur_mono.tv_sec - prev_mono.tv_sec; > + > /* Time should not go backwards */ > ASSERT_LE(prev_rtc_read, rtc_read); > - /* Time should not increase more then 1s at a time */ > - ASSERT_GE(prev_rtc_read + 1, rtc_read); > + /* Time should not increase more then elapsed time + 1s */ > + ASSERT_GE(prev_rtc_read + delta_s + 1, rtc_read); > > /* Sleep 11ms to avoid killing / overheating the RTC */ > nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000); > > prev_rtc_read = rtc_read; > + prev_mono = cur_mono; > iter_count++; > } while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC); > > -- > 2.54.0.545.g6539524ca2-goog > -- Alexandre Belloni, co-owner and COO, Bootlin Embedded Linux and Kernel engineering https://bootlin.com

