xref: /aosp_15_r20/external/lz4/programs/timefn.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker /*
2*27162e4eSAndroid Build Coastguard Worker   timefn.c - portable time measurement functions
3*27162e4eSAndroid Build Coastguard Worker   Copyright (C) Yann Collet 2023
4*27162e4eSAndroid Build Coastguard Worker 
5*27162e4eSAndroid Build Coastguard Worker   GPL v2 License
6*27162e4eSAndroid Build Coastguard Worker 
7*27162e4eSAndroid Build Coastguard Worker   This program is free software; you can redistribute it and/or modify
8*27162e4eSAndroid Build Coastguard Worker   it under the terms of the GNU General Public License as published by
9*27162e4eSAndroid Build Coastguard Worker   the Free Software Foundation; either version 2 of the License, or
10*27162e4eSAndroid Build Coastguard Worker   (at your option) any later version.
11*27162e4eSAndroid Build Coastguard Worker 
12*27162e4eSAndroid Build Coastguard Worker   This program is distributed in the hope that it will be useful,
13*27162e4eSAndroid Build Coastguard Worker   but WITHOUT ANY WARRANTY; without even the implied warranty of
14*27162e4eSAndroid Build Coastguard Worker   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*27162e4eSAndroid Build Coastguard Worker   GNU General Public License for more details.
16*27162e4eSAndroid Build Coastguard Worker 
17*27162e4eSAndroid Build Coastguard Worker   You should have received a copy of the GNU General Public License along
18*27162e4eSAndroid Build Coastguard Worker   with this program; if not, write to the Free Software Foundation, Inc.,
19*27162e4eSAndroid Build Coastguard Worker   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20*27162e4eSAndroid Build Coastguard Worker 
21*27162e4eSAndroid Build Coastguard Worker   You can contact the author at :
22*27162e4eSAndroid Build Coastguard Worker   - LZ4 source repository : https://github.com/lz4/lz4
23*27162e4eSAndroid Build Coastguard Worker   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
24*27162e4eSAndroid Build Coastguard Worker */
25*27162e4eSAndroid Build Coastguard Worker 
26*27162e4eSAndroid Build Coastguard Worker /* ===  Dependencies  === */
27*27162e4eSAndroid Build Coastguard Worker 
28*27162e4eSAndroid Build Coastguard Worker #include "timefn.h"
29*27162e4eSAndroid Build Coastguard Worker #include <time.h> /* CLOCK_MONOTONIC, TIME_UTC */
30*27162e4eSAndroid Build Coastguard Worker 
31*27162e4eSAndroid Build Coastguard Worker /*-****************************************
32*27162e4eSAndroid Build Coastguard Worker  *  Time functions
33*27162e4eSAndroid Build Coastguard Worker  ******************************************/
34*27162e4eSAndroid Build Coastguard Worker 
35*27162e4eSAndroid Build Coastguard Worker #if defined(_WIN32) /* Windows */
36*27162e4eSAndroid Build Coastguard Worker 
37*27162e4eSAndroid Build Coastguard Worker #    include <stdio.h>   /* perror */
38*27162e4eSAndroid Build Coastguard Worker #    include <stdlib.h>  /* abort */
39*27162e4eSAndroid Build Coastguard Worker #    include <windows.h> /* LARGE_INTEGER */
40*27162e4eSAndroid Build Coastguard Worker 
TIME_getTime(void)41*27162e4eSAndroid Build Coastguard Worker TIME_t TIME_getTime(void)
42*27162e4eSAndroid Build Coastguard Worker {
43*27162e4eSAndroid Build Coastguard Worker     static LARGE_INTEGER ticksPerSecond;
44*27162e4eSAndroid Build Coastguard Worker     static int init = 0;
45*27162e4eSAndroid Build Coastguard Worker     if (!init) {
46*27162e4eSAndroid Build Coastguard Worker         if (!QueryPerformanceFrequency(&ticksPerSecond)) {
47*27162e4eSAndroid Build Coastguard Worker             perror("timefn::QueryPerformanceFrequency");
48*27162e4eSAndroid Build Coastguard Worker             abort();
49*27162e4eSAndroid Build Coastguard Worker         }
50*27162e4eSAndroid Build Coastguard Worker         init = 1;
51*27162e4eSAndroid Build Coastguard Worker     }
52*27162e4eSAndroid Build Coastguard Worker     {
53*27162e4eSAndroid Build Coastguard Worker         TIME_t r;
54*27162e4eSAndroid Build Coastguard Worker         LARGE_INTEGER x;
55*27162e4eSAndroid Build Coastguard Worker         QueryPerformanceCounter(&x);
56*27162e4eSAndroid Build Coastguard Worker         r.t = (Duration_ns)(x.QuadPart * 1000000000ULL / ticksPerSecond.QuadPart);
57*27162e4eSAndroid Build Coastguard Worker         return r;
58*27162e4eSAndroid Build Coastguard Worker     }
59*27162e4eSAndroid Build Coastguard Worker }
60*27162e4eSAndroid Build Coastguard Worker 
61*27162e4eSAndroid Build Coastguard Worker #elif defined(__APPLE__) && defined(__MACH__)
62*27162e4eSAndroid Build Coastguard Worker 
63*27162e4eSAndroid Build Coastguard Worker #    include <mach/mach_time.h> /* mach_timebase_info_data_t, mach_timebase_info, mach_absolute_time */
64*27162e4eSAndroid Build Coastguard Worker 
TIME_getTime(void)65*27162e4eSAndroid Build Coastguard Worker TIME_t TIME_getTime(void)
66*27162e4eSAndroid Build Coastguard Worker {
67*27162e4eSAndroid Build Coastguard Worker     static mach_timebase_info_data_t rate;
68*27162e4eSAndroid Build Coastguard Worker     static int init = 0;
69*27162e4eSAndroid Build Coastguard Worker     if (!init) {
70*27162e4eSAndroid Build Coastguard Worker         mach_timebase_info(&rate);
71*27162e4eSAndroid Build Coastguard Worker         init = 1;
72*27162e4eSAndroid Build Coastguard Worker     }
73*27162e4eSAndroid Build Coastguard Worker     {
74*27162e4eSAndroid Build Coastguard Worker         TIME_t r;
75*27162e4eSAndroid Build Coastguard Worker         r.t = mach_absolute_time() * (Duration_ns)rate.numer
76*27162e4eSAndroid Build Coastguard Worker                 / (Duration_ns)rate.denom;
77*27162e4eSAndroid Build Coastguard Worker         return r;
78*27162e4eSAndroid Build Coastguard Worker     }
79*27162e4eSAndroid Build Coastguard Worker }
80*27162e4eSAndroid Build Coastguard Worker 
81*27162e4eSAndroid Build Coastguard Worker 
82*27162e4eSAndroid Build Coastguard Worker /* POSIX.1-2001 (optional) */
83*27162e4eSAndroid Build Coastguard Worker #elif defined(CLOCK_MONOTONIC)
84*27162e4eSAndroid Build Coastguard Worker 
85*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h>   /* abort */
86*27162e4eSAndroid Build Coastguard Worker #include <stdio.h>    /* perror */
87*27162e4eSAndroid Build Coastguard Worker 
TIME_getTime(void)88*27162e4eSAndroid Build Coastguard Worker TIME_t TIME_getTime(void)
89*27162e4eSAndroid Build Coastguard Worker {
90*27162e4eSAndroid Build Coastguard Worker     /* time must be initialized, othersize it may fail msan test.
91*27162e4eSAndroid Build Coastguard Worker      * No good reason, likely a limitation of timespec_get() for some target */
92*27162e4eSAndroid Build Coastguard Worker     struct timespec time = { 0, 0 };
93*27162e4eSAndroid Build Coastguard Worker     if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) {
94*27162e4eSAndroid Build Coastguard Worker         perror("timefn::clock_gettime(CLOCK_MONOTONIC)");
95*27162e4eSAndroid Build Coastguard Worker         abort();
96*27162e4eSAndroid Build Coastguard Worker     }
97*27162e4eSAndroid Build Coastguard Worker     {   TIME_t r;
98*27162e4eSAndroid Build Coastguard Worker         r.t = (Duration_ns)time.tv_sec * 1000000000ULL
99*27162e4eSAndroid Build Coastguard Worker                 + (Duration_ns)time.tv_nsec;
100*27162e4eSAndroid Build Coastguard Worker         return r;
101*27162e4eSAndroid Build Coastguard Worker     }
102*27162e4eSAndroid Build Coastguard Worker }
103*27162e4eSAndroid Build Coastguard Worker 
104*27162e4eSAndroid Build Coastguard Worker 
105*27162e4eSAndroid Build Coastguard Worker /* C11 requires support of timespec_get().
106*27162e4eSAndroid Build Coastguard Worker  * However, FreeBSD 11 claims C11 compliance while lacking timespec_get().
107*27162e4eSAndroid Build Coastguard Worker  * Double confirm timespec_get() support by checking the definition of TIME_UTC.
108*27162e4eSAndroid Build Coastguard Worker  * However, some versions of Android manage to simultaneously define TIME_UTC
109*27162e4eSAndroid Build Coastguard Worker  * and lack timespec_get() support... */
110*27162e4eSAndroid Build Coastguard Worker #elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
111*27162e4eSAndroid Build Coastguard Worker         && defined(TIME_UTC) && !defined(__ANDROID__)
112*27162e4eSAndroid Build Coastguard Worker 
113*27162e4eSAndroid Build Coastguard Worker #    include <stdio.h>  /* perror */
114*27162e4eSAndroid Build Coastguard Worker #    include <stdlib.h> /* abort */
115*27162e4eSAndroid Build Coastguard Worker 
TIME_getTime(void)116*27162e4eSAndroid Build Coastguard Worker TIME_t TIME_getTime(void)
117*27162e4eSAndroid Build Coastguard Worker {
118*27162e4eSAndroid Build Coastguard Worker     /* time must be initialized, othersize it may fail msan test */
119*27162e4eSAndroid Build Coastguard Worker     struct timespec time = { 0, 0 };
120*27162e4eSAndroid Build Coastguard Worker     if (timespec_get(&time, TIME_UTC) != TIME_UTC) {
121*27162e4eSAndroid Build Coastguard Worker         perror("timefn::timespec_get(TIME_UTC)");
122*27162e4eSAndroid Build Coastguard Worker         abort();
123*27162e4eSAndroid Build Coastguard Worker     }
124*27162e4eSAndroid Build Coastguard Worker     {
125*27162e4eSAndroid Build Coastguard Worker         TIME_t r;
126*27162e4eSAndroid Build Coastguard Worker         r.t = (Duration_ns)time.tv_sec * 1000000000ULL
127*27162e4eSAndroid Build Coastguard Worker                 + (Duration_ns)time.tv_nsec;
128*27162e4eSAndroid Build Coastguard Worker         return r;
129*27162e4eSAndroid Build Coastguard Worker     }
130*27162e4eSAndroid Build Coastguard Worker }
131*27162e4eSAndroid Build Coastguard Worker 
132*27162e4eSAndroid Build Coastguard Worker #else /* relies on standard C90 (note : clock_t produces wrong measurements \
133*27162e4eSAndroid Build Coastguard Worker          for multi-threaded workloads) */
134*27162e4eSAndroid Build Coastguard Worker 
TIME_getTime(void)135*27162e4eSAndroid Build Coastguard Worker TIME_t TIME_getTime(void)
136*27162e4eSAndroid Build Coastguard Worker {
137*27162e4eSAndroid Build Coastguard Worker     TIME_t r;
138*27162e4eSAndroid Build Coastguard Worker     r.t = (Duration_ns)clock() * 1000000000ULL / CLOCKS_PER_SEC;
139*27162e4eSAndroid Build Coastguard Worker     return r;
140*27162e4eSAndroid Build Coastguard Worker }
141*27162e4eSAndroid Build Coastguard Worker 
142*27162e4eSAndroid Build Coastguard Worker #    define TIME_MT_MEASUREMENTS_NOT_SUPPORTED
143*27162e4eSAndroid Build Coastguard Worker 
144*27162e4eSAndroid Build Coastguard Worker #endif
145*27162e4eSAndroid Build Coastguard Worker 
146*27162e4eSAndroid Build Coastguard Worker /* ==== Common functions, valid for all time API ==== */
147*27162e4eSAndroid Build Coastguard Worker 
TIME_span_ns(TIME_t clockStart,TIME_t clockEnd)148*27162e4eSAndroid Build Coastguard Worker Duration_ns TIME_span_ns(TIME_t clockStart, TIME_t clockEnd)
149*27162e4eSAndroid Build Coastguard Worker {
150*27162e4eSAndroid Build Coastguard Worker     return clockEnd.t - clockStart.t;
151*27162e4eSAndroid Build Coastguard Worker }
152*27162e4eSAndroid Build Coastguard Worker 
TIME_clockSpan_ns(TIME_t clockStart)153*27162e4eSAndroid Build Coastguard Worker Duration_ns TIME_clockSpan_ns(TIME_t clockStart)
154*27162e4eSAndroid Build Coastguard Worker {
155*27162e4eSAndroid Build Coastguard Worker     TIME_t const clockEnd = TIME_getTime();
156*27162e4eSAndroid Build Coastguard Worker     return TIME_span_ns(clockStart, clockEnd);
157*27162e4eSAndroid Build Coastguard Worker }
158*27162e4eSAndroid Build Coastguard Worker 
TIME_waitForNextTick(void)159*27162e4eSAndroid Build Coastguard Worker void TIME_waitForNextTick(void)
160*27162e4eSAndroid Build Coastguard Worker {
161*27162e4eSAndroid Build Coastguard Worker     TIME_t const clockStart = TIME_getTime();
162*27162e4eSAndroid Build Coastguard Worker     TIME_t clockEnd;
163*27162e4eSAndroid Build Coastguard Worker     do {
164*27162e4eSAndroid Build Coastguard Worker         clockEnd = TIME_getTime();
165*27162e4eSAndroid Build Coastguard Worker     } while (TIME_span_ns(clockStart, clockEnd) == 0);
166*27162e4eSAndroid Build Coastguard Worker }
167*27162e4eSAndroid Build Coastguard Worker 
TIME_support_MT_measurements(void)168*27162e4eSAndroid Build Coastguard Worker int TIME_support_MT_measurements(void)
169*27162e4eSAndroid Build Coastguard Worker {
170*27162e4eSAndroid Build Coastguard Worker #if defined(TIME_MT_MEASUREMENTS_NOT_SUPPORTED)
171*27162e4eSAndroid Build Coastguard Worker     return 0;
172*27162e4eSAndroid Build Coastguard Worker #else
173*27162e4eSAndroid Build Coastguard Worker     return 1;
174*27162e4eSAndroid Build Coastguard Worker #endif
175*27162e4eSAndroid Build Coastguard Worker }
176