^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* Make sure timers don't return early
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * by: john stultz (johnstul@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * John Stultz (john.stultz@linaro.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (C) Copyright IBM 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) Copyright Linaro 2013 2015
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Licensed under the GPLv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * To build:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * $ gcc nanosleep.c -o nanosleep -lrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This program is free software: you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * the Free Software Foundation, either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sys/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "../kselftest.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define NSEC_PER_SEC 1000000000ULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CLOCK_REALTIME 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define CLOCK_MONOTONIC 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CLOCK_PROCESS_CPUTIME_ID 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CLOCK_THREAD_CPUTIME_ID 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CLOCK_MONOTONIC_RAW 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define CLOCK_REALTIME_COARSE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CLOCK_MONOTONIC_COARSE 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CLOCK_BOOTTIME 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CLOCK_REALTIME_ALARM 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CLOCK_BOOTTIME_ALARM 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define CLOCK_HWSPECIFIC 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CLOCK_TAI 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define NR_CLOCKIDS 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define UNSUPPORTED 0xf00f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) char *clockstring(int clockid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) switch (clockid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case CLOCK_REALTIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return "CLOCK_REALTIME";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case CLOCK_MONOTONIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return "CLOCK_MONOTONIC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case CLOCK_PROCESS_CPUTIME_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return "CLOCK_PROCESS_CPUTIME_ID";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) case CLOCK_THREAD_CPUTIME_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return "CLOCK_THREAD_CPUTIME_ID";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case CLOCK_MONOTONIC_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return "CLOCK_MONOTONIC_RAW";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case CLOCK_REALTIME_COARSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return "CLOCK_REALTIME_COARSE";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case CLOCK_MONOTONIC_COARSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return "CLOCK_MONOTONIC_COARSE";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case CLOCK_BOOTTIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return "CLOCK_BOOTTIME";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case CLOCK_REALTIME_ALARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return "CLOCK_REALTIME_ALARM";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case CLOCK_BOOTTIME_ALARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return "CLOCK_BOOTTIME_ALARM";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case CLOCK_TAI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return "CLOCK_TAI";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return "UNKNOWN_CLOCKID";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* returns 1 if a <= b, 0 otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline int in_order(struct timespec a, struct timespec b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (a.tv_sec < b.tv_sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (a.tv_sec > b.tv_sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (a.tv_nsec > b.tv_nsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct timespec timespec_add(struct timespec ts, unsigned long long ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ts.tv_nsec += ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) while (ts.tv_nsec >= NSEC_PER_SEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ts.tv_nsec -= NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ts.tv_sec++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int nanosleep_test(int clockid, long long ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct timespec now, target, rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* First check abs time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (clock_gettime(clockid, &now))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return UNSUPPORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) target = timespec_add(now, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return UNSUPPORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) clock_gettime(clockid, &now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!in_order(target, now))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Second check reltime */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) clock_gettime(clockid, &now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) rel.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) rel.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) rel = timespec_add(rel, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) target = timespec_add(now, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) clock_nanosleep(clockid, 0, &rel, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) clock_gettime(clockid, &now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!in_order(target, now))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) long long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int clockid, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Skip cputime clockids since nanosleep won't increment cputime */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) clockid == CLOCK_THREAD_CPUTIME_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) clockid == CLOCK_HWSPECIFIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) printf("Nanosleep %-31s ", clockstring(clockid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) length = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) while (length <= (NSEC_PER_SEC * 10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret = nanosleep_test(clockid, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (ret == UNSUPPORTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) printf("[UNSUPPORTED]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) printf("[FAILED]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) length *= 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) printf("[OK]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ksft_exit_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }