xref: /freebsd/sys/contrib/zstd/programs/timefn.c (revision 2b9c00cb6bd9392645dc8afca59cf57c42df4e2d)
1*2b9c00cbSConrad Meyer /*
2*2b9c00cbSConrad Meyer  * Copyright (c) 2019-present, Yann Collet, Facebook, Inc.
3*2b9c00cbSConrad Meyer  * All rights reserved.
4*2b9c00cbSConrad Meyer  *
5*2b9c00cbSConrad Meyer  * This source code is licensed under both the BSD-style license (found in the
6*2b9c00cbSConrad Meyer  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*2b9c00cbSConrad Meyer  * in the COPYING file in the root directory of this source tree).
8*2b9c00cbSConrad Meyer  * You may select, at your option, one of the above-listed licenses.
9*2b9c00cbSConrad Meyer  */
10*2b9c00cbSConrad Meyer 
11*2b9c00cbSConrad Meyer 
12*2b9c00cbSConrad Meyer /* ===  Dependencies  === */
13*2b9c00cbSConrad Meyer 
14*2b9c00cbSConrad Meyer #include "timefn.h"
15*2b9c00cbSConrad Meyer 
16*2b9c00cbSConrad Meyer 
17*2b9c00cbSConrad Meyer /*-****************************************
18*2b9c00cbSConrad Meyer *  Time functions
19*2b9c00cbSConrad Meyer ******************************************/
20*2b9c00cbSConrad Meyer 
21*2b9c00cbSConrad Meyer #if defined(_WIN32)   /* Windows */
22*2b9c00cbSConrad Meyer 
23*2b9c00cbSConrad Meyer #include <stdlib.h>   /* abort */
24*2b9c00cbSConrad Meyer #include <stdio.h>    /* perror */
25*2b9c00cbSConrad Meyer 
26*2b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
27*2b9c00cbSConrad Meyer 
28*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
29*2b9c00cbSConrad Meyer {
30*2b9c00cbSConrad Meyer     static LARGE_INTEGER ticksPerSecond;
31*2b9c00cbSConrad Meyer     static int init = 0;
32*2b9c00cbSConrad Meyer     if (!init) {
33*2b9c00cbSConrad Meyer         if (!QueryPerformanceFrequency(&ticksPerSecond)) {
34*2b9c00cbSConrad Meyer             perror("timefn::QueryPerformanceFrequency");
35*2b9c00cbSConrad Meyer             abort();
36*2b9c00cbSConrad Meyer         }
37*2b9c00cbSConrad Meyer         init = 1;
38*2b9c00cbSConrad Meyer     }
39*2b9c00cbSConrad Meyer     return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
40*2b9c00cbSConrad Meyer }
41*2b9c00cbSConrad Meyer 
42*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
43*2b9c00cbSConrad Meyer {
44*2b9c00cbSConrad Meyer     static LARGE_INTEGER ticksPerSecond;
45*2b9c00cbSConrad Meyer     static int init = 0;
46*2b9c00cbSConrad Meyer     if (!init) {
47*2b9c00cbSConrad Meyer         if (!QueryPerformanceFrequency(&ticksPerSecond)) {
48*2b9c00cbSConrad Meyer             perror("timefn::QueryPerformanceFrequency");
49*2b9c00cbSConrad Meyer             abort();
50*2b9c00cbSConrad Meyer         }
51*2b9c00cbSConrad Meyer         init = 1;
52*2b9c00cbSConrad Meyer     }
53*2b9c00cbSConrad Meyer     return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
54*2b9c00cbSConrad Meyer }
55*2b9c00cbSConrad Meyer 
56*2b9c00cbSConrad Meyer 
57*2b9c00cbSConrad Meyer 
58*2b9c00cbSConrad Meyer #elif defined(__APPLE__) && defined(__MACH__)
59*2b9c00cbSConrad Meyer 
60*2b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
61*2b9c00cbSConrad Meyer 
62*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
63*2b9c00cbSConrad Meyer {
64*2b9c00cbSConrad Meyer     static mach_timebase_info_data_t rate;
65*2b9c00cbSConrad Meyer     static int init = 0;
66*2b9c00cbSConrad Meyer     if (!init) {
67*2b9c00cbSConrad Meyer         mach_timebase_info(&rate);
68*2b9c00cbSConrad Meyer         init = 1;
69*2b9c00cbSConrad Meyer     }
70*2b9c00cbSConrad Meyer     return (((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom))/1000ULL;
71*2b9c00cbSConrad Meyer }
72*2b9c00cbSConrad Meyer 
73*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
74*2b9c00cbSConrad Meyer {
75*2b9c00cbSConrad Meyer     static mach_timebase_info_data_t rate;
76*2b9c00cbSConrad Meyer     static int init = 0;
77*2b9c00cbSConrad Meyer     if (!init) {
78*2b9c00cbSConrad Meyer         mach_timebase_info(&rate);
79*2b9c00cbSConrad Meyer         init = 1;
80*2b9c00cbSConrad Meyer     }
81*2b9c00cbSConrad Meyer     return ((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom);
82*2b9c00cbSConrad Meyer }
83*2b9c00cbSConrad Meyer 
84*2b9c00cbSConrad Meyer 
85*2b9c00cbSConrad Meyer 
86*2b9c00cbSConrad Meyer #elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
87*2b9c00cbSConrad Meyer     && defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */
88*2b9c00cbSConrad Meyer 
89*2b9c00cbSConrad Meyer #include <stdlib.h>   /* abort */
90*2b9c00cbSConrad Meyer #include <stdio.h>    /* perror */
91*2b9c00cbSConrad Meyer 
92*2b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void)
93*2b9c00cbSConrad Meyer {
94*2b9c00cbSConrad Meyer     /* time must be initialized, othersize it may fail msan test.
95*2b9c00cbSConrad Meyer      * No good reason, likely a limitation of timespec_get() for some target */
96*2b9c00cbSConrad Meyer     UTIL_time_t time = UTIL_TIME_INITIALIZER;
97*2b9c00cbSConrad Meyer     if (timespec_get(&time, TIME_UTC) != TIME_UTC) {
98*2b9c00cbSConrad Meyer         perror("timefn::timespec_get");
99*2b9c00cbSConrad Meyer         abort();
100*2b9c00cbSConrad Meyer     }
101*2b9c00cbSConrad Meyer     return time;
102*2b9c00cbSConrad Meyer }
103*2b9c00cbSConrad Meyer 
104*2b9c00cbSConrad Meyer static UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
105*2b9c00cbSConrad Meyer {
106*2b9c00cbSConrad Meyer     UTIL_time_t diff;
107*2b9c00cbSConrad Meyer     if (end.tv_nsec < begin.tv_nsec) {
108*2b9c00cbSConrad Meyer         diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
109*2b9c00cbSConrad Meyer         diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
110*2b9c00cbSConrad Meyer     } else {
111*2b9c00cbSConrad Meyer         diff.tv_sec = end.tv_sec - begin.tv_sec;
112*2b9c00cbSConrad Meyer         diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
113*2b9c00cbSConrad Meyer     }
114*2b9c00cbSConrad Meyer     return diff;
115*2b9c00cbSConrad Meyer }
116*2b9c00cbSConrad Meyer 
117*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
118*2b9c00cbSConrad Meyer {
119*2b9c00cbSConrad Meyer     UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
120*2b9c00cbSConrad Meyer     PTime micro = 0;
121*2b9c00cbSConrad Meyer     micro += 1000000ULL * diff.tv_sec;
122*2b9c00cbSConrad Meyer     micro += diff.tv_nsec / 1000ULL;
123*2b9c00cbSConrad Meyer     return micro;
124*2b9c00cbSConrad Meyer }
125*2b9c00cbSConrad Meyer 
126*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
127*2b9c00cbSConrad Meyer {
128*2b9c00cbSConrad Meyer     UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
129*2b9c00cbSConrad Meyer     PTime nano = 0;
130*2b9c00cbSConrad Meyer     nano += 1000000000ULL * diff.tv_sec;
131*2b9c00cbSConrad Meyer     nano += diff.tv_nsec;
132*2b9c00cbSConrad Meyer     return nano;
133*2b9c00cbSConrad Meyer }
134*2b9c00cbSConrad Meyer 
135*2b9c00cbSConrad Meyer 
136*2b9c00cbSConrad Meyer 
137*2b9c00cbSConrad Meyer #else   /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */
138*2b9c00cbSConrad Meyer 
139*2b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void) { return clock(); }
140*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
141*2b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
142*2b9c00cbSConrad Meyer 
143*2b9c00cbSConrad Meyer #endif
144*2b9c00cbSConrad Meyer 
145*2b9c00cbSConrad Meyer 
146*2b9c00cbSConrad Meyer 
147*2b9c00cbSConrad Meyer /* returns time span in microseconds */
148*2b9c00cbSConrad Meyer PTime UTIL_clockSpanMicro(UTIL_time_t clockStart )
149*2b9c00cbSConrad Meyer {
150*2b9c00cbSConrad Meyer     UTIL_time_t const clockEnd = UTIL_getTime();
151*2b9c00cbSConrad Meyer     return UTIL_getSpanTimeMicro(clockStart, clockEnd);
152*2b9c00cbSConrad Meyer }
153*2b9c00cbSConrad Meyer 
154*2b9c00cbSConrad Meyer /* returns time span in microseconds */
155*2b9c00cbSConrad Meyer PTime UTIL_clockSpanNano(UTIL_time_t clockStart )
156*2b9c00cbSConrad Meyer {
157*2b9c00cbSConrad Meyer     UTIL_time_t const clockEnd = UTIL_getTime();
158*2b9c00cbSConrad Meyer     return UTIL_getSpanTimeNano(clockStart, clockEnd);
159*2b9c00cbSConrad Meyer }
160*2b9c00cbSConrad Meyer 
161*2b9c00cbSConrad Meyer void UTIL_waitForNextTick(void)
162*2b9c00cbSConrad Meyer {
163*2b9c00cbSConrad Meyer     UTIL_time_t const clockStart = UTIL_getTime();
164*2b9c00cbSConrad Meyer     UTIL_time_t clockEnd;
165*2b9c00cbSConrad Meyer     do {
166*2b9c00cbSConrad Meyer         clockEnd = UTIL_getTime();
167*2b9c00cbSConrad Meyer     } while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
168*2b9c00cbSConrad Meyer }
169