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