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