1314817Sngie/* $NetBSD: t_clock_gettime.c,v 1.3 2017/01/13 21:30:41 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2008 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Frank Kardel. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie 32272343Sngie/*- 33272343Sngie * Copyright (c) 2006 Frank Kardel 34272343Sngie * All rights reserved. 35272343Sngie * 36272343Sngie * Redistribution and use in source and binary forms, with or without 37272343Sngie * modification, are permitted provided that the following conditions 38272343Sngie * are met: 39272343Sngie * 1. Redistributions of source code must retain the above copyright 40272343Sngie * notice, this list of conditions and the following disclaimer. 41272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 42272343Sngie * notice, this list of conditions and the following disclaimer in the 43272343Sngie * documentation and/or other materials provided with the distribution. 44272343Sngie * 45272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55272343Sngie * POSSIBILITY OF SUCH DAMAGE. 56272343Sngie */ 57272343Sngie 58272343Sngie#include <sys/cdefs.h> 59272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\ 60272343Sngie The NetBSD Foundation, inc. All rights reserved."); 61314817Sngie__RCSID("$NetBSD: t_clock_gettime.c,v 1.3 2017/01/13 21:30:41 christos Exp $"); 62272343Sngie 63272343Sngie#include <sys/param.h> 64272343Sngie#include <sys/sysctl.h> 65272343Sngie 66272343Sngie 67272343Sngie#include <atf-c.h> 68272343Sngie#include <errno.h> 69314817Sngie#include <limits.h> 70272343Sngie#include <stdio.h> 71314817Sngie#include <stdint.h> 72272343Sngie#include <stdlib.h> 73272343Sngie#include <string.h> 74272343Sngie#include <time.h> 75272343Sngie#include <unistd.h> 76272343Sngie 77276478Sngie#include "h_macros.h" 78272343Sngie 79272343Sngie#define MINPOSDIFF 15000000 /* 15 ms for now */ 80272343Sngie#define TIMEOUT 5 81272343Sngie 82272343Sngie#define TC_HARDWARE "kern.timecounter.hardware" 83272343Sngie#define TC_CHOICE "kern.timecounter.choice" 84272343Sngie 85272343Sngiestatic void 86272343Sngiecheck_timecounter(void) 87272343Sngie{ 88272343Sngie struct timespec tsa, tsb, tsl, res; 89272343Sngie long long mindiff = INTMAX_MAX; 90272343Sngie time_t endlimit; 91272343Sngie 92272343Sngie#define CL(x) \ 93272343Sngie do { \ 94272343Sngie if ((x) != -1) \ 95272343Sngie break; \ 96272343Sngie atf_tc_fail_nonfatal("%s: %s", #x, strerror(errno)); \ 97272343Sngie return; \ 98272343Sngie } while (0) 99272343Sngie 100272343Sngie CL(clock_gettime(CLOCK_REALTIME, &tsa)); 101272343Sngie tsl = tsa; 102272343Sngie 103272343Sngie CL(time(&endlimit)); 104272343Sngie endlimit += TIMEOUT + 1; 105272343Sngie 106272343Sngie while ((time_t)tsa.tv_sec < endlimit) { 107272343Sngie long long diff; 108272343Sngie 109272343Sngie CL(clock_gettime(CLOCK_REALTIME, &tsb)); 110272343Sngie diff = 1000000000LL * (tsb.tv_sec - tsa.tv_sec) 111272343Sngie + tsb.tv_nsec - tsa.tv_nsec; 112272343Sngie 113272343Sngie if (diff > 0 && mindiff > diff) 114272343Sngie mindiff = diff; 115272343Sngie 116272343Sngie if (diff < 0 || diff > MINPOSDIFF) { 117272343Sngie long long elapsed; 118272343Sngie (void)printf("%stime TSA: 0x%jx.%08jx, TSB: 0x%jx.%08jx, " 119272343Sngie "diff = %lld nsec, ", (diff < 0) ? "BAD " : "", 120272343Sngie (uintmax_t)tsa.tv_sec, (uintmax_t)tsa.tv_nsec, 121272343Sngie (uintmax_t)tsb.tv_sec, (uintmax_t)tsb.tv_nsec, diff); 122272343Sngie 123272343Sngie elapsed = 1000000000LL * (tsb.tv_sec - tsl.tv_sec) 124272343Sngie + tsb.tv_nsec - tsl.tv_nsec; 125272343Sngie 126272343Sngie 127272343Sngie (void)printf("%lld nsec\n", elapsed); 128272343Sngie tsl = tsb; 129272343Sngie 130272343Sngie ATF_CHECK(diff >= 0); 131272343Sngie if (diff < 0) 132272343Sngie return; 133272343Sngie } 134272343Sngie 135272343Sngie tsa.tv_sec = tsb.tv_sec; 136272343Sngie tsa.tv_nsec = tsb.tv_nsec; 137272343Sngie } 138272343Sngie 139272343Sngie if (clock_getres(CLOCK_REALTIME, &res) == 0) { 140272343Sngie long long r = res.tv_sec * 1000000000 + res.tv_nsec; 141272343Sngie 142272343Sngie (void)printf("Claimed resolution: %lld nsec (%f Hz) or " 143272343Sngie "better\n", r, 1.0 / r * 1e9); 144272343Sngie (void)printf("Observed minimum non zero delta: %lld " 145272343Sngie "nsec\n", mindiff); 146272343Sngie } 147272343Sngie 148272343Sngie#undef CL 149272343Sngie} 150272343Sngie 151272343SngieATF_TC(clock_gettime_real); 152272343SngieATF_TC_HEAD(clock_gettime_real, tc) 153272343Sngie{ 154272343Sngie atf_tc_set_md_var(tc, "require.user", "root"); 155272343Sngie atf_tc_set_md_var(tc, "descr", 156272343Sngie "Checks the monotonicity of the CLOCK_REALTIME implementation"); 157272343Sngie atf_tc_set_md_var(tc, "timeout", "300"); 158272343Sngie} 159272343Sngie 160272343SngieATF_TC_BODY(clock_gettime_real, tc) 161272343Sngie{ 162272343Sngie char name[128], cbuf[512], ctrbuf[10240]; 163272343Sngie size_t cbufsiz = sizeof(cbuf); 164272343Sngie size_t ctrbufsiz = sizeof(ctrbuf); 165272343Sngie const char *p; 166272343Sngie char *save; 167272343Sngie int quality, n; 168272343Sngie 169272343Sngie if (sysctlbyname(TC_HARDWARE, cbuf, &cbufsiz, NULL, 0) != 0) { 170272343Sngie (void)printf("\nChecking legacy time implementation " 171272343Sngie "for %d seconds\n", TIMEOUT); 172272343Sngie check_timecounter(); 173272343Sngie return; 174272343Sngie /* NOTREACHED */ 175272343Sngie } 176272343Sngie (void)printf("%s = %s\n", TC_HARDWARE, cbuf); 177272343Sngie REQUIRE_LIBC(save = strdup(cbuf), NULL); 178272343Sngie 179272343Sngie RL(sysctlbyname(TC_CHOICE, ctrbuf, &ctrbufsiz, NULL, 0)); 180272343Sngie (void)printf("%s = %s\n", TC_CHOICE, ctrbuf); 181272343Sngie 182272343Sngie for (p = ctrbuf, n = 0; sscanf(p, "%127[^(](q=%d, f=%*u Hz)%*[ ]%n", 183272343Sngie name, &quality, &n) == 2; p += n) { 184272343Sngie struct timespec ts; 185272343Sngie int ret; 186272343Sngie 187272343Sngie if (quality < 0) 188272343Sngie continue; 189272343Sngie 190272343Sngie (void)printf("\nChecking %s for %d seconds\n", name, TIMEOUT); 191272343Sngie CHECK_LIBC(ret = sysctlbyname(TC_HARDWARE, NULL, 0, 192272343Sngie name, strlen(name)), -1); 193272343Sngie if (ret == -1) 194272343Sngie continue; 195272343Sngie 196272343Sngie /* wait a bit to select new counter in clockinterrupt */ 197272343Sngie ts.tv_sec = 0; 198272343Sngie ts.tv_nsec = 100000000; 199272343Sngie (void)nanosleep(&ts, NULL); 200272343Sngie 201272343Sngie check_timecounter(); 202272343Sngie } 203272343Sngie 204272343Sngie RL(sysctlbyname(TC_HARDWARE, NULL, 0, save, strlen(save))); 205272343Sngie} 206272343Sngie 207272343SngieATF_TP_ADD_TCS(tp) 208272343Sngie{ 209272343Sngie 210272343Sngie ATF_TP_ADD_TC(tp, clock_gettime_real); 211272343Sngie 212272343Sngie return atf_no_error(); 213272343Sngie} 214