0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
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)
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
0128 sigfillset(&act.sa_mask);
0129 act.sa_flags = 0;
0130 act.sa_handler = sigalarm;
0131 sigaction(signum, &act, NULL);
0132
0133
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);
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 }