[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220331190612.22162-2-mat.jonczyk@o2.pl>
Date: Thu, 31 Mar 2022 21:06:12 +0200
From: Mateusz Jończyk <mat.jonczyk@...pl>
To: linux-kernel@...r.kernel.org, linux-rtc@...r.kernel.org,
linux-kselftest@...r.kernel.org
Cc: Mateusz Jończyk <mat.jonczyk@...pl>,
Alessandro Zummo <a.zummo@...ertech.it>,
Alexandre Belloni <alexandre.belloni@...tlin.com>,
Shuah Khan <shuah@...nel.org>
Subject: [PATCH 2/2] [RFC] selftests/rtc: read RTC alarm time many times in a row
This is the userspace part of the test unit.
This patch depends on
commit 2aaa36e95ea5 ("selftests/rtc: continuously read RTC in a loop for 30s")
Existing code casts "struct rtc_time *" to "struct tm *", like so:
gmtime_r(&secs, (struct tm *)&tm);
This is incorrect, because sizeof(struct tm) > sizeof(struct rtc_time)
(on Ubuntu 20.04 at least) and gmtime_r overwrites part of the stack.
I'll submit a fix for this in mainline soon, but for now I'm defining
timestamp_to_rtc_time() here.
TODO:
- some logic improvements, without much impact on the core algorithm.
Signed-off-by: Mateusz Jończyk <mat.jonczyk@...pl>
Cc: Alessandro Zummo <a.zummo@...ertech.it>
Cc: Alexandre Belloni <alexandre.belloni@...tlin.com>
Cc: Shuah Khan <shuah@...nel.org>
---
tools/testing/selftests/rtc/rtctest.c | 81 ++++++++++++++++++++++++++-
tools/testing/selftests/rtc/settings | 2 +-
2 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/rtc/rtctest.c b/tools/testing/selftests/rtc/rtctest.c
index 2b9d929a24ed..7e5f2f1c00ef 100644
--- a/tools/testing/selftests/rtc/rtctest.c
+++ b/tools/testing/selftests/rtc/rtctest.c
@@ -62,7 +62,21 @@ static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time)
.tm_year = rtc_time->tm_year,
};
- return mktime(&tm_time);
+ return timegm(&tm_time);
+}
+
+static void timestamp_to_rtc_time(time_t timestamp, struct rtc_time *rtc_time)
+{
+ struct tm tm_time;
+
+ gmtime_r(×tamp, &tm_time);
+
+ rtc_time->tm_sec = tm_time.tm_sec;
+ rtc_time->tm_min = tm_time.tm_min;
+ rtc_time->tm_hour = tm_time.tm_hour;
+ rtc_time->tm_mday = tm_time.tm_mday;
+ rtc_time->tm_mon = tm_time.tm_mon;
+ rtc_time->tm_year = tm_time.tm_year;
}
static void nanosleep_with_retries(long ns)
@@ -228,6 +242,71 @@ TEST_F(rtc, alarm_alm_set) {
ASSERT_EQ(new, secs);
}
+TEST_F_TIMEOUT(rtc, alarm_read_loop, READ_LOOP_DURATION_SEC + 2) {
+ int rc;
+ long iter_count = 0;
+ struct rtc_time tm;
+ struct timeval start, curr;
+ time_t secs;
+
+ rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+ ASSERT_NE(-1, rc);
+
+ // 60s is for clocks that only support minute resolution of RTC alarm
+ secs = rtc_time_to_timestamp(&tm) + READ_LOOP_DURATION_SEC + 60 + 2;
+ timestamp_to_rtc_time(secs, &tm);
+
+ rc = ioctl(self->fd, RTC_ALM_SET, &tm);
+ if (rc == -1) {
+ ASSERT_EQ(EINVAL, errno);
+ TH_LOG("skip alarms are not supported.");
+ return;
+ }
+
+ rc = ioctl(self->fd, RTC_AIE_ON, NULL);
+ ASSERT_NE(-1, rc);
+
+ TH_LOG("Continuously reading RTC alarm time for %ds (with %dms breaks after every read).",
+ READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS);
+
+ gettimeofday(&start, NULL);
+
+ secs = 0;
+
+ do {
+ // TODO: use appropriate directory
+ // TODO: fail gracefully if the kernel support does not exist
+ FILE *wkalarm_file = fopen("/sys/kernel/debug/rtc/rtc0/wakealarm_raw", "r");
+ long long wkalarm_time;
+
+ ASSERT_NE(wkalarm_file, NULL);
+
+ rc = fscanf(wkalarm_file, "%lld", &wkalarm_time);
+ fclose(wkalarm_file);
+
+ ASSERT_EQ(rc, 1);
+ ASSERT_NE(secs, -1);
+ // TODO: use another value as placeholder,
+ // TODO: check if wkalarm_time matches alarm time we set
+ // previously
+ if (secs == 0)
+ secs = wkalarm_time;
+
+ ASSERT_EQ(wkalarm_time, secs);
+
+ // Sleep 11ms to avoid killing / overheating the RTC
+ nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000);
+
+ gettimeofday(&curr, NULL);
+ iter_count++;
+ } while (curr.tv_sec <= start.tv_sec + READ_LOOP_DURATION_SEC);
+
+ TH_LOG("Performed %ld RTC alarm time reads.", iter_count);
+
+ rc = ioctl(self->fd, RTC_AIE_OFF, NULL);
+ ASSERT_NE(-1, rc);
+}
+
TEST_F(rtc, alarm_wkalm_set) {
struct timeval tv = { .tv_sec = ALARM_DELTA + 2 };
struct rtc_wkalrm alarm = { 0 };
diff --git a/tools/testing/selftests/rtc/settings b/tools/testing/selftests/rtc/settings
index 0c1a2075d5f3..b478e684846a 100644
--- a/tools/testing/selftests/rtc/settings
+++ b/tools/testing/selftests/rtc/settings
@@ -1 +1 @@
-timeout=210
+timeout=240
--
2.25.1
Powered by blists - more mailing lists