1*57718be8SEnji Cooper /* $NetBSD: t_clock_gettime.c,v 1.1 2011/10/15 06:42:16 jruoho Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2008 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation 8*57718be8SEnji Cooper * by Frank Kardel. 9*57718be8SEnji Cooper * 10*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 11*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 12*57718be8SEnji Cooper * are met: 13*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 14*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 15*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 16*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 17*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 18*57718be8SEnji Cooper * 19*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 30*57718be8SEnji Cooper */ 31*57718be8SEnji Cooper 32*57718be8SEnji Cooper /*- 33*57718be8SEnji Cooper * Copyright (c) 2006 Frank Kardel 34*57718be8SEnji Cooper * All rights reserved. 35*57718be8SEnji Cooper * 36*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 37*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 38*57718be8SEnji Cooper * are met: 39*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 40*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 41*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 42*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 43*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 44*57718be8SEnji Cooper * 45*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 56*57718be8SEnji Cooper */ 57*57718be8SEnji Cooper 58*57718be8SEnji Cooper #include <sys/cdefs.h> 59*57718be8SEnji Cooper __COPYRIGHT("@(#) Copyright (c) 2008\ 60*57718be8SEnji Cooper The NetBSD Foundation, inc. All rights reserved."); 61*57718be8SEnji Cooper __RCSID("$NetBSD: t_clock_gettime.c,v 1.1 2011/10/15 06:42:16 jruoho Exp $"); 62*57718be8SEnji Cooper 63*57718be8SEnji Cooper #include <sys/param.h> 64*57718be8SEnji Cooper #include <sys/sysctl.h> 65*57718be8SEnji Cooper 66*57718be8SEnji Cooper #include <machine/int_limits.h> 67*57718be8SEnji Cooper 68*57718be8SEnji Cooper #include <atf-c.h> 69*57718be8SEnji Cooper #include <errno.h> 70*57718be8SEnji Cooper #include <stdio.h> 71*57718be8SEnji Cooper #include <stdlib.h> 72*57718be8SEnji Cooper #include <string.h> 73*57718be8SEnji Cooper #include <time.h> 74*57718be8SEnji Cooper #include <unistd.h> 75*57718be8SEnji Cooper 76*57718be8SEnji Cooper #include "../../../h_macros.h" 77*57718be8SEnji Cooper 78*57718be8SEnji Cooper #define MINPOSDIFF 15000000 /* 15 ms for now */ 79*57718be8SEnji Cooper #define TIMEOUT 5 80*57718be8SEnji Cooper 81*57718be8SEnji Cooper #define TC_HARDWARE "kern.timecounter.hardware" 82*57718be8SEnji Cooper #define TC_CHOICE "kern.timecounter.choice" 83*57718be8SEnji Cooper 84*57718be8SEnji Cooper static void 85*57718be8SEnji Cooper check_timecounter(void) 86*57718be8SEnji Cooper { 87*57718be8SEnji Cooper struct timespec tsa, tsb, tsl, res; 88*57718be8SEnji Cooper long long mindiff = INTMAX_MAX; 89*57718be8SEnji Cooper time_t endlimit; 90*57718be8SEnji Cooper 91*57718be8SEnji Cooper #define CL(x) \ 92*57718be8SEnji Cooper do { \ 93*57718be8SEnji Cooper if ((x) != -1) \ 94*57718be8SEnji Cooper break; \ 95*57718be8SEnji Cooper atf_tc_fail_nonfatal("%s: %s", #x, strerror(errno)); \ 96*57718be8SEnji Cooper return; \ 97*57718be8SEnji Cooper } while (0) 98*57718be8SEnji Cooper 99*57718be8SEnji Cooper CL(clock_gettime(CLOCK_REALTIME, &tsa)); 100*57718be8SEnji Cooper tsl = tsa; 101*57718be8SEnji Cooper 102*57718be8SEnji Cooper CL(time(&endlimit)); 103*57718be8SEnji Cooper endlimit += TIMEOUT + 1; 104*57718be8SEnji Cooper 105*57718be8SEnji Cooper while ((time_t)tsa.tv_sec < endlimit) { 106*57718be8SEnji Cooper long long diff; 107*57718be8SEnji Cooper 108*57718be8SEnji Cooper CL(clock_gettime(CLOCK_REALTIME, &tsb)); 109*57718be8SEnji Cooper diff = 1000000000LL * (tsb.tv_sec - tsa.tv_sec) 110*57718be8SEnji Cooper + tsb.tv_nsec - tsa.tv_nsec; 111*57718be8SEnji Cooper 112*57718be8SEnji Cooper if (diff > 0 && mindiff > diff) 113*57718be8SEnji Cooper mindiff = diff; 114*57718be8SEnji Cooper 115*57718be8SEnji Cooper if (diff < 0 || diff > MINPOSDIFF) { 116*57718be8SEnji Cooper long long elapsed; 117*57718be8SEnji Cooper (void)printf("%stime TSA: 0x%jx.%08jx, TSB: 0x%jx.%08jx, " 118*57718be8SEnji Cooper "diff = %lld nsec, ", (diff < 0) ? "BAD " : "", 119*57718be8SEnji Cooper (uintmax_t)tsa.tv_sec, (uintmax_t)tsa.tv_nsec, 120*57718be8SEnji Cooper (uintmax_t)tsb.tv_sec, (uintmax_t)tsb.tv_nsec, diff); 121*57718be8SEnji Cooper 122*57718be8SEnji Cooper elapsed = 1000000000LL * (tsb.tv_sec - tsl.tv_sec) 123*57718be8SEnji Cooper + tsb.tv_nsec - tsl.tv_nsec; 124*57718be8SEnji Cooper 125*57718be8SEnji Cooper 126*57718be8SEnji Cooper (void)printf("%lld nsec\n", elapsed); 127*57718be8SEnji Cooper tsl = tsb; 128*57718be8SEnji Cooper 129*57718be8SEnji Cooper ATF_CHECK(diff >= 0); 130*57718be8SEnji Cooper if (diff < 0) 131*57718be8SEnji Cooper return; 132*57718be8SEnji Cooper } 133*57718be8SEnji Cooper 134*57718be8SEnji Cooper tsa.tv_sec = tsb.tv_sec; 135*57718be8SEnji Cooper tsa.tv_nsec = tsb.tv_nsec; 136*57718be8SEnji Cooper } 137*57718be8SEnji Cooper 138*57718be8SEnji Cooper if (clock_getres(CLOCK_REALTIME, &res) == 0) { 139*57718be8SEnji Cooper long long r = res.tv_sec * 1000000000 + res.tv_nsec; 140*57718be8SEnji Cooper 141*57718be8SEnji Cooper (void)printf("Claimed resolution: %lld nsec (%f Hz) or " 142*57718be8SEnji Cooper "better\n", r, 1.0 / r * 1e9); 143*57718be8SEnji Cooper (void)printf("Observed minimum non zero delta: %lld " 144*57718be8SEnji Cooper "nsec\n", mindiff); 145*57718be8SEnji Cooper } 146*57718be8SEnji Cooper 147*57718be8SEnji Cooper #undef CL 148*57718be8SEnji Cooper } 149*57718be8SEnji Cooper 150*57718be8SEnji Cooper ATF_TC(clock_gettime_real); 151*57718be8SEnji Cooper ATF_TC_HEAD(clock_gettime_real, tc) 152*57718be8SEnji Cooper { 153*57718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 154*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 155*57718be8SEnji Cooper "Checks the monotonicity of the CLOCK_REALTIME implementation"); 156*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "300"); 157*57718be8SEnji Cooper } 158*57718be8SEnji Cooper 159*57718be8SEnji Cooper ATF_TC_BODY(clock_gettime_real, tc) 160*57718be8SEnji Cooper { 161*57718be8SEnji Cooper char name[128], cbuf[512], ctrbuf[10240]; 162*57718be8SEnji Cooper size_t cbufsiz = sizeof(cbuf); 163*57718be8SEnji Cooper size_t ctrbufsiz = sizeof(ctrbuf); 164*57718be8SEnji Cooper const char *p; 165*57718be8SEnji Cooper char *save; 166*57718be8SEnji Cooper int quality, n; 167*57718be8SEnji Cooper 168*57718be8SEnji Cooper if (sysctlbyname(TC_HARDWARE, cbuf, &cbufsiz, NULL, 0) != 0) { 169*57718be8SEnji Cooper (void)printf("\nChecking legacy time implementation " 170*57718be8SEnji Cooper "for %d seconds\n", TIMEOUT); 171*57718be8SEnji Cooper check_timecounter(); 172*57718be8SEnji Cooper return; 173*57718be8SEnji Cooper /* NOTREACHED */ 174*57718be8SEnji Cooper } 175*57718be8SEnji Cooper (void)printf("%s = %s\n", TC_HARDWARE, cbuf); 176*57718be8SEnji Cooper REQUIRE_LIBC(save = strdup(cbuf), NULL); 177*57718be8SEnji Cooper 178*57718be8SEnji Cooper RL(sysctlbyname(TC_CHOICE, ctrbuf, &ctrbufsiz, NULL, 0)); 179*57718be8SEnji Cooper (void)printf("%s = %s\n", TC_CHOICE, ctrbuf); 180*57718be8SEnji Cooper 181*57718be8SEnji Cooper for (p = ctrbuf, n = 0; sscanf(p, "%127[^(](q=%d, f=%*u Hz)%*[ ]%n", 182*57718be8SEnji Cooper name, &quality, &n) == 2; p += n) { 183*57718be8SEnji Cooper struct timespec ts; 184*57718be8SEnji Cooper int ret; 185*57718be8SEnji Cooper 186*57718be8SEnji Cooper if (quality < 0) 187*57718be8SEnji Cooper continue; 188*57718be8SEnji Cooper 189*57718be8SEnji Cooper (void)printf("\nChecking %s for %d seconds\n", name, TIMEOUT); 190*57718be8SEnji Cooper CHECK_LIBC(ret = sysctlbyname(TC_HARDWARE, NULL, 0, 191*57718be8SEnji Cooper name, strlen(name)), -1); 192*57718be8SEnji Cooper if (ret == -1) 193*57718be8SEnji Cooper continue; 194*57718be8SEnji Cooper 195*57718be8SEnji Cooper /* wait a bit to select new counter in clockinterrupt */ 196*57718be8SEnji Cooper ts.tv_sec = 0; 197*57718be8SEnji Cooper ts.tv_nsec = 100000000; 198*57718be8SEnji Cooper (void)nanosleep(&ts, NULL); 199*57718be8SEnji Cooper 200*57718be8SEnji Cooper check_timecounter(); 201*57718be8SEnji Cooper } 202*57718be8SEnji Cooper 203*57718be8SEnji Cooper RL(sysctlbyname(TC_HARDWARE, NULL, 0, save, strlen(save))); 204*57718be8SEnji Cooper } 205*57718be8SEnji Cooper 206*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 207*57718be8SEnji Cooper { 208*57718be8SEnji Cooper 209*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, clock_gettime_real); 210*57718be8SEnji Cooper 211*57718be8SEnji Cooper return atf_no_error(); 212*57718be8SEnji Cooper } 213