Back to home page

OSCL-LXR

 
 

    


0001 /* alarmtimer suspend test
0002  *      John Stultz (john.stultz@linaro.org)
0003  *              (C) Copyright Linaro 2013
0004  *              Licensed under the GPLv2
0005  *
0006  *   This test makes sure the alarmtimer & RTC wakeup code is
0007  *   functioning.
0008  *
0009  *  To build:
0010  *  $ gcc alarmtimer-suspend.c -o alarmtimer-suspend -lrt
0011  *
0012  *   This program is free software: you can redistribute it and/or modify
0013  *   it under the terms of the GNU General Public License as published by
0014  *   the Free Software Foundation, either version 2 of the License, or
0015  *   (at your option) any later version.
0016  *
0017  *   This program is distributed in the hope that it will be useful,
0018  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0019  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0020  *   GNU General Public License for more details.
0021  */
0022 
0023 
0024 #include <stdio.h>
0025 #include <unistd.h>
0026 #include <time.h>
0027 #include <string.h>
0028 #include <signal.h>
0029 #include <stdlib.h>
0030 #include <pthread.h>
0031 #include "../kselftest.h"
0032 
0033 #define CLOCK_REALTIME          0
0034 #define CLOCK_MONOTONIC         1
0035 #define CLOCK_PROCESS_CPUTIME_ID    2
0036 #define CLOCK_THREAD_CPUTIME_ID     3
0037 #define CLOCK_MONOTONIC_RAW     4
0038 #define CLOCK_REALTIME_COARSE       5
0039 #define CLOCK_MONOTONIC_COARSE      6
0040 #define CLOCK_BOOTTIME          7
0041 #define CLOCK_REALTIME_ALARM        8
0042 #define CLOCK_BOOTTIME_ALARM        9
0043 #define CLOCK_HWSPECIFIC        10
0044 #define CLOCK_TAI           11
0045 #define NR_CLOCKIDS         12
0046 
0047 
0048 #define NSEC_PER_SEC 1000000000ULL
0049 #define UNREASONABLE_LAT (NSEC_PER_SEC * 5) /* hopefully we resume in 5 secs */
0050 
0051 #define SUSPEND_SECS 15
0052 int alarmcount;
0053 int alarm_clock_id;
0054 struct timespec start_time;
0055 
0056 
0057 char *clockstring(int clockid)
0058 {
0059     switch (clockid) {
0060     case CLOCK_REALTIME:
0061         return "CLOCK_REALTIME";
0062     case CLOCK_MONOTONIC:
0063         return "CLOCK_MONOTONIC";
0064     case CLOCK_PROCESS_CPUTIME_ID:
0065         return "CLOCK_PROCESS_CPUTIME_ID";
0066     case CLOCK_THREAD_CPUTIME_ID:
0067         return "CLOCK_THREAD_CPUTIME_ID";
0068     case CLOCK_MONOTONIC_RAW:
0069         return "CLOCK_MONOTONIC_RAW";
0070     case CLOCK_REALTIME_COARSE:
0071         return "CLOCK_REALTIME_COARSE";
0072     case CLOCK_MONOTONIC_COARSE:
0073         return "CLOCK_MONOTONIC_COARSE";
0074     case CLOCK_BOOTTIME:
0075         return "CLOCK_BOOTTIME";
0076     case CLOCK_REALTIME_ALARM:
0077         return "CLOCK_REALTIME_ALARM";
0078     case CLOCK_BOOTTIME_ALARM:
0079         return "CLOCK_BOOTTIME_ALARM";
0080     case CLOCK_TAI:
0081         return "CLOCK_TAI";
0082     }
0083     return "UNKNOWN_CLOCKID";
0084 }
0085 
0086 
0087 long long timespec_sub(struct timespec a, struct timespec b)
0088 {
0089     long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
0090 
0091     ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
0092     return ret;
0093 }
0094 
0095 int final_ret;
0096 
0097 void sigalarm(int signo)
0098 {
0099     long long delta_ns;
0100     struct timespec ts;
0101 
0102     clock_gettime(alarm_clock_id, &ts);
0103     alarmcount++;
0104 
0105     delta_ns = timespec_sub(start_time, ts);
0106     delta_ns -= NSEC_PER_SEC * SUSPEND_SECS * alarmcount;
0107 
0108     printf("ALARM(%i): %ld:%ld latency: %lld ns ", alarmcount, ts.tv_sec,
0109                             ts.tv_nsec, delta_ns);
0110 
0111     if (delta_ns > UNREASONABLE_LAT) {
0112         printf("[FAIL]\n");
0113         final_ret = -1;
0114     } else
0115         printf("[OK]\n");
0116 
0117 }
0118 
0119 int main(void)
0120 {
0121     timer_t tm1;
0122     struct itimerspec its1, its2;
0123     struct sigevent se;
0124     struct sigaction act;
0125     int signum = SIGRTMAX;
0126 
0127     /* Set up signal handler: */
0128     sigfillset(&act.sa_mask);
0129     act.sa_flags = 0;
0130     act.sa_handler = sigalarm;
0131     sigaction(signum, &act, NULL);
0132 
0133     /* Set up timer: */
0134     memset(&se, 0, sizeof(se));
0135     se.sigev_notify = SIGEV_SIGNAL;
0136     se.sigev_signo = signum;
0137     se.sigev_value.sival_int = 0;
0138 
0139     for (alarm_clock_id = CLOCK_REALTIME_ALARM;
0140             alarm_clock_id <= CLOCK_BOOTTIME_ALARM;
0141             alarm_clock_id++) {
0142 
0143         alarmcount = 0;
0144         if (timer_create(alarm_clock_id, &se, &tm1) == -1) {
0145             printf("timer_create failed, %s unsupported?\n",
0146                     clockstring(alarm_clock_id));
0147             break;
0148         }
0149 
0150         clock_gettime(alarm_clock_id, &start_time);
0151         printf("Start time (%s): %ld:%ld\n", clockstring(alarm_clock_id),
0152                 start_time.tv_sec, start_time.tv_nsec);
0153         printf("Setting alarm for every %i seconds\n", SUSPEND_SECS);
0154         its1.it_value = start_time;
0155         its1.it_value.tv_sec += SUSPEND_SECS;
0156         its1.it_interval.tv_sec = SUSPEND_SECS;
0157         its1.it_interval.tv_nsec = 0;
0158 
0159         timer_settime(tm1, TIMER_ABSTIME, &its1, &its2);
0160 
0161         while (alarmcount < 5)
0162             sleep(1); /* First 5 alarms, do nothing */
0163 
0164         printf("Starting suspend loops\n");
0165         while (alarmcount < 10) {
0166             int ret;
0167 
0168             sleep(3);
0169             ret = system("echo mem > /sys/power/state");
0170             if (ret)
0171                 break;
0172         }
0173         timer_delete(tm1);
0174     }
0175     if (final_ret)
0176         return ksft_exit_fail();
0177     return ksft_exit_pass();
0178 }