diff options
| author | John Stultz <john.stultz@linaro.org> | 2015-03-11 20:40:01 -0400 |
|---|---|---|
| committer | Shuah Khan <shuahkh@osg.samsung.com> | 2015-03-12 15:22:13 -0400 |
| commit | c5fffcb2bd4e2fdc37875fc4368db49ac927d6df (patch) | |
| tree | cc4098d78a0c9b76bde153cc8de231d36b4c58c7 /tools/testing/selftests/timers | |
| parent | ed3fe34a2a4e0c9f184a178c48acf20c7acf244e (diff) | |
selftests/timers: Add nsleep-lat test from timetest suite
Adds my nanosleep latency test from the timetest suite.
This checks to make sure we don't see "unreasonable"
latencies (> 40ms) when calling nanosleep.
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Tested-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Diffstat (limited to 'tools/testing/selftests/timers')
| -rw-r--r-- | tools/testing/selftests/timers/Makefile | 3 | ||||
| -rw-r--r-- | tools/testing/selftests/timers/nsleep-lat.c | 190 |
2 files changed, 192 insertions, 1 deletions
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile index fcb7c2fcafe5..dae9ee76b74b 100644 --- a/tools/testing/selftests/timers/Makefile +++ b/tools/testing/selftests/timers/Makefile | |||
| @@ -2,13 +2,14 @@ CC = $(CROSS_COMPILE)gcc | |||
| 2 | BUILD_FLAGS = -DKTEST | 2 | BUILD_FLAGS = -DKTEST |
| 3 | CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) | 3 | CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) |
| 4 | LDFLAGS += -lrt -lpthread | 4 | LDFLAGS += -lrt -lpthread |
| 5 | bins = posix_timers nanosleep inconsistency-check | 5 | bins = posix_timers nanosleep inconsistency-check nsleep-lat |
| 6 | 6 | ||
| 7 | all: ${bins} | 7 | all: ${bins} |
| 8 | 8 | ||
| 9 | run_tests: all | 9 | run_tests: all |
| 10 | ./posix_timers | 10 | ./posix_timers |
| 11 | ./nanosleep | 11 | ./nanosleep |
| 12 | ./nsleep-lat | ||
| 12 | ./inconsistency-check | 13 | ./inconsistency-check |
| 13 | clean: | 14 | clean: |
| 14 | rm -f ${bins} | 15 | rm -f ${bins} |
diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c new file mode 100644 index 000000000000..2d7898fda0f1 --- /dev/null +++ b/tools/testing/selftests/timers/nsleep-lat.c | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* Measure nanosleep timer latency | ||
| 2 | * by: john stultz (john.stultz@linaro.org) | ||
| 3 | * (C) Copyright Linaro 2013 | ||
| 4 | * Licensed under the GPLv2 | ||
| 5 | * | ||
| 6 | * To build: | ||
| 7 | * $ gcc nsleep-lat.c -o nsleep-lat -lrt | ||
| 8 | * | ||
| 9 | * This program is free software: you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation, either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <stdio.h> | ||
| 21 | #include <stdlib.h> | ||
| 22 | #include <time.h> | ||
| 23 | #include <sys/time.h> | ||
| 24 | #include <sys/timex.h> | ||
| 25 | #include <string.h> | ||
| 26 | #include <signal.h> | ||
| 27 | #ifdef KTEST | ||
| 28 | #include "../kselftest.h" | ||
| 29 | #else | ||
| 30 | static inline int ksft_exit_pass(void) | ||
| 31 | { | ||
| 32 | exit(0); | ||
| 33 | } | ||
| 34 | static inline int ksft_exit_fail(void) | ||
| 35 | { | ||
| 36 | exit(1); | ||
| 37 | } | ||
| 38 | #endif | ||
| 39 | |||
| 40 | #define NSEC_PER_SEC 1000000000ULL | ||
| 41 | |||
| 42 | #define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */ | ||
| 43 | |||
| 44 | |||
| 45 | #define CLOCK_REALTIME 0 | ||
| 46 | #define CLOCK_MONOTONIC 1 | ||
| 47 | #define CLOCK_PROCESS_CPUTIME_ID 2 | ||
| 48 | #define CLOCK_THREAD_CPUTIME_ID 3 | ||
| 49 | #define CLOCK_MONOTONIC_RAW 4 | ||
| 50 | #define CLOCK_REALTIME_COARSE 5 | ||
| 51 | #define CLOCK_MONOTONIC_COARSE 6 | ||
| 52 | #define CLOCK_BOOTTIME 7 | ||
| 53 | #define CLOCK_REALTIME_ALARM 8 | ||
| 54 | #define CLOCK_BOOTTIME_ALARM 9 | ||
| 55 | #define CLOCK_HWSPECIFIC 10 | ||
| 56 | #define CLOCK_TAI 11 | ||
| 57 | #define NR_CLOCKIDS 12 | ||
| 58 | |||
| 59 | #define UNSUPPORTED 0xf00f | ||
| 60 | |||
| 61 | char *clockstring(int clockid) | ||
| 62 | { | ||
| 63 | switch (clockid) { | ||
| 64 | case CLOCK_REALTIME: | ||
| 65 | return "CLOCK_REALTIME"; | ||
| 66 | case CLOCK_MONOTONIC: | ||
| 67 | return "CLOCK_MONOTONIC"; | ||
| 68 | case CLOCK_PROCESS_CPUTIME_ID: | ||
| 69 | return "CLOCK_PROCESS_CPUTIME_ID"; | ||
| 70 | case CLOCK_THREAD_CPUTIME_ID: | ||
| 71 | return "CLOCK_THREAD_CPUTIME_ID"; | ||
| 72 | case CLOCK_MONOTONIC_RAW: | ||
| 73 | return "CLOCK_MONOTONIC_RAW"; | ||
| 74 | case CLOCK_REALTIME_COARSE: | ||
| 75 | return "CLOCK_REALTIME_COARSE"; | ||
| 76 | case CLOCK_MONOTONIC_COARSE: | ||
| 77 | return "CLOCK_MONOTONIC_COARSE"; | ||
| 78 | case CLOCK_BOOTTIME: | ||
| 79 | return "CLOCK_BOOTTIME"; | ||
| 80 | case CLOCK_REALTIME_ALARM: | ||
| 81 | return "CLOCK_REALTIME_ALARM"; | ||
| 82 | case CLOCK_BOOTTIME_ALARM: | ||
| 83 | return "CLOCK_BOOTTIME_ALARM"; | ||
| 84 | case CLOCK_TAI: | ||
| 85 | return "CLOCK_TAI"; | ||
| 86 | }; | ||
| 87 | return "UNKNOWN_CLOCKID"; | ||
| 88 | } | ||
| 89 | |||
| 90 | struct timespec timespec_add(struct timespec ts, unsigned long long ns) | ||
| 91 | { | ||
| 92 | ts.tv_nsec += ns; | ||
| 93 | while (ts.tv_nsec >= NSEC_PER_SEC) { | ||
| 94 | ts.tv_nsec -= NSEC_PER_SEC; | ||
| 95 | ts.tv_sec++; | ||
| 96 | } | ||
| 97 | return ts; | ||
| 98 | } | ||
| 99 | |||
| 100 | |||
| 101 | long long timespec_sub(struct timespec a, struct timespec b) | ||
| 102 | { | ||
| 103 | long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec; | ||
| 104 | |||
| 105 | ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec; | ||
| 106 | return ret; | ||
| 107 | } | ||
| 108 | |||
| 109 | int nanosleep_lat_test(int clockid, long long ns) | ||
| 110 | { | ||
| 111 | struct timespec start, end, target; | ||
| 112 | long long latency = 0; | ||
| 113 | int i, count; | ||
| 114 | |||
| 115 | target.tv_sec = ns/NSEC_PER_SEC; | ||
| 116 | target.tv_nsec = ns%NSEC_PER_SEC; | ||
| 117 | |||
| 118 | if (clock_gettime(clockid, &start)) | ||
| 119 | return UNSUPPORTED; | ||
| 120 | if (clock_nanosleep(clockid, 0, &target, NULL)) | ||
| 121 | return UNSUPPORTED; | ||
| 122 | |||
| 123 | count = 10; | ||
| 124 | |||
| 125 | /* First check relative latency */ | ||
| 126 | clock_gettime(clockid, &start); | ||
| 127 | for (i = 0; i < count; i++) | ||
| 128 | clock_nanosleep(clockid, 0, &target, NULL); | ||
| 129 | clock_gettime(clockid, &end); | ||
| 130 | |||
| 131 | if (((timespec_sub(start, end)/count)-ns) > UNRESONABLE_LATENCY) { | ||
| 132 | printf("Large rel latency: %lld ns :", (timespec_sub(start, end)/count)-ns); | ||
| 133 | return -1; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* Next check absolute latency */ | ||
| 137 | for (i = 0; i < count; i++) { | ||
| 138 | clock_gettime(clockid, &start); | ||
| 139 | target = timespec_add(start, ns); | ||
| 140 | clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL); | ||
| 141 | clock_gettime(clockid, &end); | ||
| 142 | latency += timespec_sub(target, end); | ||
| 143 | } | ||
| 144 | |||
| 145 | if (latency/count > UNRESONABLE_LATENCY) { | ||
| 146 | printf("Large abs latency: %lld ns :", latency/count); | ||
| 147 | return -1; | ||
| 148 | } | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | int main(int argc, char **argv) | ||
| 156 | { | ||
| 157 | long long length; | ||
| 158 | int clockid, ret; | ||
| 159 | |||
| 160 | for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) { | ||
| 161 | |||
| 162 | /* Skip cputime clockids since nanosleep won't increment cputime */ | ||
| 163 | if (clockid == CLOCK_PROCESS_CPUTIME_ID || | ||
| 164 | clockid == CLOCK_THREAD_CPUTIME_ID || | ||
| 165 | clockid == CLOCK_HWSPECIFIC) | ||
| 166 | continue; | ||
| 167 | |||
| 168 | printf("nsleep latency %-26s ", clockstring(clockid)); | ||
| 169 | |||
| 170 | length = 10; | ||
| 171 | while (length <= (NSEC_PER_SEC * 10)) { | ||
| 172 | ret = nanosleep_lat_test(clockid, length); | ||
| 173 | if (ret) | ||
| 174 | break; | ||
| 175 | length *= 100; | ||
| 176 | |||
| 177 | } | ||
| 178 | |||
| 179 | if (ret == UNSUPPORTED) { | ||
| 180 | printf("[UNSUPPORTED]\n"); | ||
| 181 | continue; | ||
| 182 | } | ||
| 183 | if (ret < 0) { | ||
| 184 | printf("[FAILED]\n"); | ||
| 185 | return ksft_exit_fail(); | ||
| 186 | } | ||
| 187 | printf("[OK]\n"); | ||
| 188 | } | ||
| 189 | return ksft_exit_pass(); | ||
| 190 | } | ||
