/* test_clock.c - tests for finding usable system clocks This file is part of the nss-pam-ldapd library. Copyright (C) 2013 Arthur de Jong This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include "compat/attrs.h" /* use clock_gettime() to see if the specified clock is supported */ static int test_clock_gettime(clockid_t c, const char *cname) { struct timespec t1 = {0, 0}; struct timespec t2 = {0, 0}; struct timespec t3 = {0, 50 * 1000 * 1000}; /* 50 msec */ struct timespec t4 = {0, 0}; long diff; int result = 0; /* see if we can get resolution (not important so ignore any failures) */ errno = 0; if (clock_getres(c, &t1)) printf(" clock %s resolution not supported: %s\n", cname, strerror(errno)); if ((t1.tv_sec != 0) || (t1.tv_nsec != 0)) printf(" clock %s resolution: %ld.%09ld\n", cname, (long)t1.tv_sec, (long)t1.tv_nsec); /* see if we can get the time */ errno = 0; if (clock_gettime(c, &t2)) { printf("FAIL clock %s get time not supported: %s\n", cname, strerror(errno)); if ((t2.tv_sec != 0) || (t2.tv_nsec != 0)) printf(" clock %s time: %ld.%09ld\n", cname, (long)t2.tv_sec, (long)t2.tv_nsec); return -1; } else printf("OK clock %s time: %ld.%09ld\n", cname, (long)t2.tv_sec, (long)t2.tv_nsec); /* quick sleep (assume we're not interrupted) */ (void)nanosleep(&t3, NULL); /* see if we can get the time again */ errno = 0; if (clock_gettime(c, &t4)) { printf("FAIL clock %s get time twice not supported: %s\n", cname, strerror(errno)); if ((t4.tv_sec != 0) || (t4.tv_nsec != 0)) printf(" clock %s time: %ld.%09ld\n", cname, (long)t4.tv_sec, (long)t4.tv_nsec); return -1; } else printf("OK clock %s time: %ld.%09ld\n", cname, (long)t4.tv_sec, (long)t4.tv_nsec); /* calculate difference */ diff = ((long)t4.tv_sec - (long)t2.tv_sec - (long)t3.tv_sec) * (long)1000000000 + ((long)t4.tv_nsec - (long)t2.tv_nsec - (long)t3.tv_nsec); if ((diff < (-10 * 1000 * 1000)) || (diff > (20 * 1000 * 1000))) { result = -1; printf("FAIL "); } else printf("OK "); printf("clock %s time diff: %s%ld.%09ld %.1f%%\n", cname, (diff < 0) ? "-" : "", (labs(diff) / 1000000000L), (labs(diff) % 1000000000L), labs(100L * diff) / (float)((long)t3.tv_sec * 1000000000L + (long)t3.tv_nsec)); return result; } /* wrapper for test_clock_gettime() that passes the clock name */ #define TEST_CLOCK_GETTIME(clock) test_clock_gettime(clock, #clock) int main(int UNUSED(argc), char UNUSED(*argv[])) { int found_clocks = 0; #ifdef CLOCK_MONOTONIC_RAW if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_RAW)) found_clocks++; #endif #ifdef CLOCK_MONOTONIC_FAST if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_FAST)) found_clocks++; #endif #ifdef CLOCK_MONOTONIC_COARSE if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_COARSE)) found_clocks++; #endif #ifdef CLOCK_MONOTONIC if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC)) found_clocks++; #endif #ifdef CLOCK_UPTIME_FAST if (!TEST_CLOCK_GETTIME(CLOCK_UPTIME_FAST)) found_clocks++; #endif #ifdef CLOCK_UPTIME if (!TEST_CLOCK_GETTIME(CLOCK_UPTIME)) found_clocks++; #endif #ifdef CLOCK_BOOTTIME if (!TEST_CLOCK_GETTIME(CLOCK_BOOTTIME)) found_clocks++; #endif #ifdef CLOCK_MONOTONIC_PRECISE if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_PRECISE)) found_clocks++; #endif #ifdef CLOCK_UPTIME_PRECISE if (!TEST_CLOCK_GETTIME(CLOCK_UPTIME_PRECISE)) found_clocks++; #endif #ifdef CLOCK_HIGHRES #if CLOCK_HIGHRES == CLOCK_MONOTONIC printf(" CLOCK_HIGHRES == CLOCK_MONOTONIC\n"); #else /* for Solaris, should be similar to CLOCK_MONOTONIC (it may be an alias) */ if (!TEST_CLOCK_GETTIME(CLOCK_HIGHRES)) found_clocks++; #endif #endif #ifdef CLOCK_REALTIME_FAST if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME_FAST)) found_clocks++; #endif #ifdef CLOCK_REALTIME_COARSE if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME_COARSE)) found_clocks++; #endif if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME)) found_clocks++; #ifdef CLOCK_REALTIME_PRECISE if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME_PRECISE)) found_clocks++; #endif printf("%d usable clocks found\n", found_clocks); return !(found_clocks > 0); }