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