xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/timers/alarmtimer-suspend.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker /* alarmtimer suspend test
2*053f45beSAndroid Build Coastguard Worker  *		John Stultz ([email protected])
3*053f45beSAndroid Build Coastguard Worker  *              (C) Copyright Linaro 2013
4*053f45beSAndroid Build Coastguard Worker  *              Licensed under the GPLv2
5*053f45beSAndroid Build Coastguard Worker  *
6*053f45beSAndroid Build Coastguard Worker  *   This test makes sure the alarmtimer & RTC wakeup code is
7*053f45beSAndroid Build Coastguard Worker  *   functioning.
8*053f45beSAndroid Build Coastguard Worker  *
9*053f45beSAndroid Build Coastguard Worker  *  To build:
10*053f45beSAndroid Build Coastguard Worker  *	$ gcc alarmtimer-suspend.c -o alarmtimer-suspend -lrt
11*053f45beSAndroid Build Coastguard Worker  *
12*053f45beSAndroid Build Coastguard Worker  *   This program is free software: you can redistribute it and/or modify
13*053f45beSAndroid Build Coastguard Worker  *   it under the terms of the GNU General Public License as published by
14*053f45beSAndroid Build Coastguard Worker  *   the Free Software Foundation, either version 2 of the License, or
15*053f45beSAndroid Build Coastguard Worker  *   (at your option) any later version.
16*053f45beSAndroid Build Coastguard Worker  *
17*053f45beSAndroid Build Coastguard Worker  *   This program is distributed in the hope that it will be useful,
18*053f45beSAndroid Build Coastguard Worker  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19*053f45beSAndroid Build Coastguard Worker  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20*053f45beSAndroid Build Coastguard Worker  *   GNU General Public License for more details.
21*053f45beSAndroid Build Coastguard Worker  */
22*053f45beSAndroid Build Coastguard Worker 
23*053f45beSAndroid Build Coastguard Worker 
24*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
25*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
26*053f45beSAndroid Build Coastguard Worker #include <time.h>
27*053f45beSAndroid Build Coastguard Worker #include <string.h>
28*053f45beSAndroid Build Coastguard Worker #include <signal.h>
29*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
30*053f45beSAndroid Build Coastguard Worker #include <pthread.h>
31*053f45beSAndroid Build Coastguard Worker #include "../kselftest.h"
32*053f45beSAndroid Build Coastguard Worker 
33*053f45beSAndroid Build Coastguard Worker #define CLOCK_REALTIME			0
34*053f45beSAndroid Build Coastguard Worker #define CLOCK_MONOTONIC			1
35*053f45beSAndroid Build Coastguard Worker #define CLOCK_PROCESS_CPUTIME_ID	2
36*053f45beSAndroid Build Coastguard Worker #define CLOCK_THREAD_CPUTIME_ID		3
37*053f45beSAndroid Build Coastguard Worker #define CLOCK_MONOTONIC_RAW		4
38*053f45beSAndroid Build Coastguard Worker #define CLOCK_REALTIME_COARSE		5
39*053f45beSAndroid Build Coastguard Worker #define CLOCK_MONOTONIC_COARSE		6
40*053f45beSAndroid Build Coastguard Worker #define CLOCK_BOOTTIME			7
41*053f45beSAndroid Build Coastguard Worker #define CLOCK_REALTIME_ALARM		8
42*053f45beSAndroid Build Coastguard Worker #define CLOCK_BOOTTIME_ALARM		9
43*053f45beSAndroid Build Coastguard Worker #define CLOCK_HWSPECIFIC		10
44*053f45beSAndroid Build Coastguard Worker #define CLOCK_TAI			11
45*053f45beSAndroid Build Coastguard Worker #define NR_CLOCKIDS			12
46*053f45beSAndroid Build Coastguard Worker 
47*053f45beSAndroid Build Coastguard Worker 
48*053f45beSAndroid Build Coastguard Worker #define NSEC_PER_SEC 1000000000ULL
49*053f45beSAndroid Build Coastguard Worker #define UNREASONABLE_LAT (NSEC_PER_SEC * 5) /* hopefully we resume in 5 secs */
50*053f45beSAndroid Build Coastguard Worker 
51*053f45beSAndroid Build Coastguard Worker #define SUSPEND_SECS 15
52*053f45beSAndroid Build Coastguard Worker int alarmcount;
53*053f45beSAndroid Build Coastguard Worker int alarm_clock_id;
54*053f45beSAndroid Build Coastguard Worker struct timespec start_time;
55*053f45beSAndroid Build Coastguard Worker 
56*053f45beSAndroid Build Coastguard Worker 
clockstring(int clockid)57*053f45beSAndroid Build Coastguard Worker char *clockstring(int clockid)
58*053f45beSAndroid Build Coastguard Worker {
59*053f45beSAndroid Build Coastguard Worker 	switch (clockid) {
60*053f45beSAndroid Build Coastguard Worker 	case CLOCK_REALTIME:
61*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_REALTIME";
62*053f45beSAndroid Build Coastguard Worker 	case CLOCK_MONOTONIC:
63*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_MONOTONIC";
64*053f45beSAndroid Build Coastguard Worker 	case CLOCK_PROCESS_CPUTIME_ID:
65*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_PROCESS_CPUTIME_ID";
66*053f45beSAndroid Build Coastguard Worker 	case CLOCK_THREAD_CPUTIME_ID:
67*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_THREAD_CPUTIME_ID";
68*053f45beSAndroid Build Coastguard Worker 	case CLOCK_MONOTONIC_RAW:
69*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_MONOTONIC_RAW";
70*053f45beSAndroid Build Coastguard Worker 	case CLOCK_REALTIME_COARSE:
71*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_REALTIME_COARSE";
72*053f45beSAndroid Build Coastguard Worker 	case CLOCK_MONOTONIC_COARSE:
73*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_MONOTONIC_COARSE";
74*053f45beSAndroid Build Coastguard Worker 	case CLOCK_BOOTTIME:
75*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_BOOTTIME";
76*053f45beSAndroid Build Coastguard Worker 	case CLOCK_REALTIME_ALARM:
77*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_REALTIME_ALARM";
78*053f45beSAndroid Build Coastguard Worker 	case CLOCK_BOOTTIME_ALARM:
79*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_BOOTTIME_ALARM";
80*053f45beSAndroid Build Coastguard Worker 	case CLOCK_TAI:
81*053f45beSAndroid Build Coastguard Worker 		return "CLOCK_TAI";
82*053f45beSAndroid Build Coastguard Worker 	}
83*053f45beSAndroid Build Coastguard Worker 	return "UNKNOWN_CLOCKID";
84*053f45beSAndroid Build Coastguard Worker }
85*053f45beSAndroid Build Coastguard Worker 
86*053f45beSAndroid Build Coastguard Worker 
timespec_sub(struct timespec a,struct timespec b)87*053f45beSAndroid Build Coastguard Worker long long timespec_sub(struct timespec a, struct timespec b)
88*053f45beSAndroid Build Coastguard Worker {
89*053f45beSAndroid Build Coastguard Worker 	long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
90*053f45beSAndroid Build Coastguard Worker 
91*053f45beSAndroid Build Coastguard Worker 	ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
92*053f45beSAndroid Build Coastguard Worker 	return ret;
93*053f45beSAndroid Build Coastguard Worker }
94*053f45beSAndroid Build Coastguard Worker 
95*053f45beSAndroid Build Coastguard Worker int final_ret;
96*053f45beSAndroid Build Coastguard Worker 
sigalarm(int signo)97*053f45beSAndroid Build Coastguard Worker void sigalarm(int signo)
98*053f45beSAndroid Build Coastguard Worker {
99*053f45beSAndroid Build Coastguard Worker 	long long delta_ns;
100*053f45beSAndroid Build Coastguard Worker 	struct timespec ts;
101*053f45beSAndroid Build Coastguard Worker 
102*053f45beSAndroid Build Coastguard Worker 	clock_gettime(alarm_clock_id, &ts);
103*053f45beSAndroid Build Coastguard Worker 	alarmcount++;
104*053f45beSAndroid Build Coastguard Worker 
105*053f45beSAndroid Build Coastguard Worker 	delta_ns = timespec_sub(start_time, ts);
106*053f45beSAndroid Build Coastguard Worker 	delta_ns -= NSEC_PER_SEC * SUSPEND_SECS * alarmcount;
107*053f45beSAndroid Build Coastguard Worker 
108*053f45beSAndroid Build Coastguard Worker 	printf("ALARM(%i): %ld:%ld latency: %lld ns ", alarmcount, ts.tv_sec,
109*053f45beSAndroid Build Coastguard Worker 							ts.tv_nsec, delta_ns);
110*053f45beSAndroid Build Coastguard Worker 
111*053f45beSAndroid Build Coastguard Worker 	if (delta_ns > UNREASONABLE_LAT) {
112*053f45beSAndroid Build Coastguard Worker 		printf("[FAIL]\n");
113*053f45beSAndroid Build Coastguard Worker 		final_ret = -1;
114*053f45beSAndroid Build Coastguard Worker 	} else
115*053f45beSAndroid Build Coastguard Worker 		printf("[OK]\n");
116*053f45beSAndroid Build Coastguard Worker 
117*053f45beSAndroid Build Coastguard Worker }
118*053f45beSAndroid Build Coastguard Worker 
main(void)119*053f45beSAndroid Build Coastguard Worker int main(void)
120*053f45beSAndroid Build Coastguard Worker {
121*053f45beSAndroid Build Coastguard Worker 	timer_t tm1;
122*053f45beSAndroid Build Coastguard Worker 	struct itimerspec its1, its2;
123*053f45beSAndroid Build Coastguard Worker 	struct sigevent se;
124*053f45beSAndroid Build Coastguard Worker 	struct sigaction act;
125*053f45beSAndroid Build Coastguard Worker 	int signum = SIGRTMAX;
126*053f45beSAndroid Build Coastguard Worker 
127*053f45beSAndroid Build Coastguard Worker 	/* Set up signal handler: */
128*053f45beSAndroid Build Coastguard Worker 	sigfillset(&act.sa_mask);
129*053f45beSAndroid Build Coastguard Worker 	act.sa_flags = 0;
130*053f45beSAndroid Build Coastguard Worker 	act.sa_handler = sigalarm;
131*053f45beSAndroid Build Coastguard Worker 	sigaction(signum, &act, NULL);
132*053f45beSAndroid Build Coastguard Worker 
133*053f45beSAndroid Build Coastguard Worker 	/* Set up timer: */
134*053f45beSAndroid Build Coastguard Worker 	memset(&se, 0, sizeof(se));
135*053f45beSAndroid Build Coastguard Worker 	se.sigev_notify = SIGEV_SIGNAL;
136*053f45beSAndroid Build Coastguard Worker 	se.sigev_signo = signum;
137*053f45beSAndroid Build Coastguard Worker 	se.sigev_value.sival_int = 0;
138*053f45beSAndroid Build Coastguard Worker 
139*053f45beSAndroid Build Coastguard Worker 	for (alarm_clock_id = CLOCK_REALTIME_ALARM;
140*053f45beSAndroid Build Coastguard Worker 			alarm_clock_id <= CLOCK_BOOTTIME_ALARM;
141*053f45beSAndroid Build Coastguard Worker 			alarm_clock_id++) {
142*053f45beSAndroid Build Coastguard Worker 
143*053f45beSAndroid Build Coastguard Worker 		alarmcount = 0;
144*053f45beSAndroid Build Coastguard Worker 		if (timer_create(alarm_clock_id, &se, &tm1) == -1) {
145*053f45beSAndroid Build Coastguard Worker 			printf("timer_create failed, %s unsupported?\n",
146*053f45beSAndroid Build Coastguard Worker 					clockstring(alarm_clock_id));
147*053f45beSAndroid Build Coastguard Worker 			break;
148*053f45beSAndroid Build Coastguard Worker 		}
149*053f45beSAndroid Build Coastguard Worker 
150*053f45beSAndroid Build Coastguard Worker 		clock_gettime(alarm_clock_id, &start_time);
151*053f45beSAndroid Build Coastguard Worker 		printf("Start time (%s): %ld:%ld\n", clockstring(alarm_clock_id),
152*053f45beSAndroid Build Coastguard Worker 				start_time.tv_sec, start_time.tv_nsec);
153*053f45beSAndroid Build Coastguard Worker 		printf("Setting alarm for every %i seconds\n", SUSPEND_SECS);
154*053f45beSAndroid Build Coastguard Worker 		its1.it_value = start_time;
155*053f45beSAndroid Build Coastguard Worker 		its1.it_value.tv_sec += SUSPEND_SECS;
156*053f45beSAndroid Build Coastguard Worker 		its1.it_interval.tv_sec = SUSPEND_SECS;
157*053f45beSAndroid Build Coastguard Worker 		its1.it_interval.tv_nsec = 0;
158*053f45beSAndroid Build Coastguard Worker 
159*053f45beSAndroid Build Coastguard Worker 		timer_settime(tm1, TIMER_ABSTIME, &its1, &its2);
160*053f45beSAndroid Build Coastguard Worker 
161*053f45beSAndroid Build Coastguard Worker 		while (alarmcount < 5)
162*053f45beSAndroid Build Coastguard Worker 			sleep(1); /* First 5 alarms, do nothing */
163*053f45beSAndroid Build Coastguard Worker 
164*053f45beSAndroid Build Coastguard Worker 		printf("Starting suspend loops\n");
165*053f45beSAndroid Build Coastguard Worker 		while (alarmcount < 10) {
166*053f45beSAndroid Build Coastguard Worker 			int ret;
167*053f45beSAndroid Build Coastguard Worker 
168*053f45beSAndroid Build Coastguard Worker 			sleep(3);
169*053f45beSAndroid Build Coastguard Worker 			ret = system("echo mem > /sys/power/state");
170*053f45beSAndroid Build Coastguard Worker 			if (ret)
171*053f45beSAndroid Build Coastguard Worker 				break;
172*053f45beSAndroid Build Coastguard Worker 		}
173*053f45beSAndroid Build Coastguard Worker 		timer_delete(tm1);
174*053f45beSAndroid Build Coastguard Worker 	}
175*053f45beSAndroid Build Coastguard Worker 	if (final_ret)
176*053f45beSAndroid Build Coastguard Worker 		return ksft_exit_fail();
177*053f45beSAndroid Build Coastguard Worker 	return ksft_exit_pass();
178*053f45beSAndroid Build Coastguard Worker }
179