Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28be3f8f authored by Greg Hackmann's avatar Greg Hackmann Committed by John Stultz
Browse files

kselftests: timers: set-timer-lat: Add one-shot timer test cases



These testcases are motivated by a recent alarmtimer regression, which
caused one-shot CLOCK_{BOOTTIME,REALTIME}_ALARM timers to become
periodic timers.

The new testcases are very similar to the existing testcases for
repeating timers.  But rather than waiting for 5 alarms, they wait for 5
seconds and verify that the alarm fired exactly once.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Miroslav Lichvar <mlichvar@redhat.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Stephen Boyd <stephen.boyd@linaro.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: default avatarGreg Hackmann <ghackmann@google.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent a524b118
Loading
Loading
Loading
Loading
+73 −13
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
 */


#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
@@ -122,17 +123,17 @@ void sigalarm(int signo)
		max_latency_ns = delta_ns;
}

void describe_timer(int flags)
void describe_timer(int flags, int interval)
{
	printf("%-22s %s ",
	printf("%-22s %s %s ",
			clockstring(clock_id),
			flags ? "ABSTIME":"RELTIME");
			flags ? "ABSTIME":"RELTIME",
			interval ? "PERIODIC":"ONE-SHOT");
}

int do_timer(int clock_id, int flags)
int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
{
	struct sigevent se;
	timer_t tm1;
	struct itimerspec its1, its2;
	int err;

@@ -146,7 +147,7 @@ int do_timer(int clock_id, int flags)
	alarmcount = 0;
	timer_fired_early = 0;

	err = timer_create(clock_id, &se, &tm1);
	err = timer_create(clock_id, &se, tm1);
	if (err) {
		if ((clock_id == CLOCK_REALTIME_ALARM) ||
		    (clock_id == CLOCK_BOOTTIME_ALARM)) {
@@ -167,19 +168,23 @@ int do_timer(int clock_id, int flags)
		its1.it_value.tv_sec = TIMER_SECS;
		its1.it_value.tv_nsec = 0;
	}
	its1.it_interval.tv_sec = TIMER_SECS;
	its1.it_interval.tv_sec = interval;
	its1.it_interval.tv_nsec = 0;

	err = timer_settime(tm1, flags, &its1, &its2);
	err = timer_settime(*tm1, flags, &its1, &its2);
	if (err) {
		printf("%s - timer_settime() failed\n", clockstring(clock_id));
		return -1;
	}

	while (alarmcount < 5)
		sleep(1);
	return 0;
}

int check_timer_latency(int flags, int interval)
{
	int err = 0;

	describe_timer(flags);
	describe_timer(flags, interval);
	printf("timer fired early: %7d : ", timer_fired_early);
	if (!timer_fired_early) {
		printf("[OK]\n");
@@ -188,10 +193,9 @@ int do_timer(int clock_id, int flags)
		err = -1;
	}

	describe_timer(flags);
	describe_timer(flags, interval);
	printf("max latency: %10lld ns : ", max_latency_ns);

	timer_delete(tm1);
	if (max_latency_ns < UNRESONABLE_LATENCY) {
		printf("[OK]\n");
	} else {
@@ -201,6 +205,60 @@ int do_timer(int clock_id, int flags)
	return err;
}

int check_alarmcount(int flags, int interval)
{
	describe_timer(flags, interval);
	printf("count: %19d : ", alarmcount);
	if (alarmcount == 1) {
		printf("[OK]\n");
		return 0;
	}
	printf("[FAILED]\n");
	return -1;
}

int do_timer(int clock_id, int flags)
{
	timer_t tm1;
	const int interval = TIMER_SECS;
	int err;

	err = setup_timer(clock_id, flags, interval, &tm1);
	if (err)
		return err;

	while (alarmcount < 5)
		sleep(1);

	timer_delete(tm1);
	return check_timer_latency(flags, interval);
}

int do_timer_oneshot(int clock_id, int flags)
{
	timer_t tm1;
	const int interval = 0;
	struct timeval timeout;
	fd_set fds;
	int err;

	err = setup_timer(clock_id, flags, interval, &tm1);
	if (err)
		return err;

	memset(&timeout, 0, sizeof(timeout));
	timeout.tv_sec = 5;
	FD_ZERO(&fds);
	do {
		err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
	} while (err == -1 && errno == EINTR);

	timer_delete(tm1);
	err = check_timer_latency(flags, interval);
	err |= check_alarmcount(flags, interval);
	return err;
}

int main(void)
{
	struct sigaction act;
@@ -226,6 +284,8 @@ int main(void)

		ret |= do_timer(clock_id, TIMER_ABSTIME);
		ret |= do_timer(clock_id, 0);
		ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME);
		ret |= do_timer_oneshot(clock_id, 0);
	}
	if (ret)
		return ksft_exit_fail();