12b9c00cbSConrad Meyer /*
2*5ff13fbcSAllan Jude * Copyright (c) Yann Collet, Facebook, Inc.
32b9c00cbSConrad Meyer * All rights reserved.
42b9c00cbSConrad Meyer *
52b9c00cbSConrad Meyer * This source code is licensed under both the BSD-style license (found in the
62b9c00cbSConrad Meyer * LICENSE file in the root directory of this source tree) and the GPLv2 (found
72b9c00cbSConrad Meyer * in the COPYING file in the root directory of this source tree).
82b9c00cbSConrad Meyer * You may select, at your option, one of the above-listed licenses.
92b9c00cbSConrad Meyer */
102b9c00cbSConrad Meyer
112b9c00cbSConrad Meyer
122b9c00cbSConrad Meyer /* === Dependencies === */
132b9c00cbSConrad Meyer
142b9c00cbSConrad Meyer #include "timefn.h"
152b9c00cbSConrad Meyer
162b9c00cbSConrad Meyer
172b9c00cbSConrad Meyer /*-****************************************
182b9c00cbSConrad Meyer * Time functions
192b9c00cbSConrad Meyer ******************************************/
202b9c00cbSConrad Meyer
212b9c00cbSConrad Meyer #if defined(_WIN32) /* Windows */
222b9c00cbSConrad Meyer
232b9c00cbSConrad Meyer #include <stdlib.h> /* abort */
242b9c00cbSConrad Meyer #include <stdio.h> /* perror */
252b9c00cbSConrad Meyer
UTIL_getTime(void)262b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
272b9c00cbSConrad Meyer
UTIL_getSpanTimeMicro(UTIL_time_t clockStart,UTIL_time_t clockEnd)282b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
292b9c00cbSConrad Meyer {
302b9c00cbSConrad Meyer static LARGE_INTEGER ticksPerSecond;
312b9c00cbSConrad Meyer static int init = 0;
322b9c00cbSConrad Meyer if (!init) {
332b9c00cbSConrad Meyer if (!QueryPerformanceFrequency(&ticksPerSecond)) {
342b9c00cbSConrad Meyer perror("timefn::QueryPerformanceFrequency");
352b9c00cbSConrad Meyer abort();
362b9c00cbSConrad Meyer }
372b9c00cbSConrad Meyer init = 1;
382b9c00cbSConrad Meyer }
392b9c00cbSConrad Meyer return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
402b9c00cbSConrad Meyer }
412b9c00cbSConrad Meyer
UTIL_getSpanTimeNano(UTIL_time_t clockStart,UTIL_time_t clockEnd)422b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
432b9c00cbSConrad Meyer {
442b9c00cbSConrad Meyer static LARGE_INTEGER ticksPerSecond;
452b9c00cbSConrad Meyer static int init = 0;
462b9c00cbSConrad Meyer if (!init) {
472b9c00cbSConrad Meyer if (!QueryPerformanceFrequency(&ticksPerSecond)) {
482b9c00cbSConrad Meyer perror("timefn::QueryPerformanceFrequency");
492b9c00cbSConrad Meyer abort();
502b9c00cbSConrad Meyer }
512b9c00cbSConrad Meyer init = 1;
522b9c00cbSConrad Meyer }
532b9c00cbSConrad Meyer return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
542b9c00cbSConrad Meyer }
552b9c00cbSConrad Meyer
562b9c00cbSConrad Meyer
572b9c00cbSConrad Meyer
582b9c00cbSConrad Meyer #elif defined(__APPLE__) && defined(__MACH__)
592b9c00cbSConrad Meyer
UTIL_getTime(void)602b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
612b9c00cbSConrad Meyer
UTIL_getSpanTimeMicro(UTIL_time_t clockStart,UTIL_time_t clockEnd)622b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
632b9c00cbSConrad Meyer {
642b9c00cbSConrad Meyer static mach_timebase_info_data_t rate;
652b9c00cbSConrad Meyer static int init = 0;
662b9c00cbSConrad Meyer if (!init) {
672b9c00cbSConrad Meyer mach_timebase_info(&rate);
682b9c00cbSConrad Meyer init = 1;
692b9c00cbSConrad Meyer }
702b9c00cbSConrad Meyer return (((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom))/1000ULL;
712b9c00cbSConrad Meyer }
722b9c00cbSConrad Meyer
UTIL_getSpanTimeNano(UTIL_time_t clockStart,UTIL_time_t clockEnd)732b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
742b9c00cbSConrad Meyer {
752b9c00cbSConrad Meyer static mach_timebase_info_data_t rate;
762b9c00cbSConrad Meyer static int init = 0;
772b9c00cbSConrad Meyer if (!init) {
782b9c00cbSConrad Meyer mach_timebase_info(&rate);
792b9c00cbSConrad Meyer init = 1;
802b9c00cbSConrad Meyer }
812b9c00cbSConrad Meyer return ((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom);
822b9c00cbSConrad Meyer }
832b9c00cbSConrad Meyer
842b9c00cbSConrad Meyer
8537f1f268SConrad Meyer /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance.
8637f1f268SConrad Meyer Android also lacks it but does define TIME_UTC. */
872b9c00cbSConrad Meyer #elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \
8837f1f268SConrad Meyer && defined(TIME_UTC) && !defined(__ANDROID__)
892b9c00cbSConrad Meyer
902b9c00cbSConrad Meyer #include <stdlib.h> /* abort */
912b9c00cbSConrad Meyer #include <stdio.h> /* perror */
922b9c00cbSConrad Meyer
UTIL_getTime(void)932b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void)
942b9c00cbSConrad Meyer {
952b9c00cbSConrad Meyer /* time must be initialized, othersize it may fail msan test.
962b9c00cbSConrad Meyer * No good reason, likely a limitation of timespec_get() for some target */
972b9c00cbSConrad Meyer UTIL_time_t time = UTIL_TIME_INITIALIZER;
982b9c00cbSConrad Meyer if (timespec_get(&time, TIME_UTC) != TIME_UTC) {
992b9c00cbSConrad Meyer perror("timefn::timespec_get");
1002b9c00cbSConrad Meyer abort();
1012b9c00cbSConrad Meyer }
1022b9c00cbSConrad Meyer return time;
1032b9c00cbSConrad Meyer }
1042b9c00cbSConrad Meyer
UTIL_getSpanTime(UTIL_time_t begin,UTIL_time_t end)1052b9c00cbSConrad Meyer static UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
1062b9c00cbSConrad Meyer {
1072b9c00cbSConrad Meyer UTIL_time_t diff;
1082b9c00cbSConrad Meyer if (end.tv_nsec < begin.tv_nsec) {
1092b9c00cbSConrad Meyer diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
1102b9c00cbSConrad Meyer diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
1112b9c00cbSConrad Meyer } else {
1122b9c00cbSConrad Meyer diff.tv_sec = end.tv_sec - begin.tv_sec;
1132b9c00cbSConrad Meyer diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
1142b9c00cbSConrad Meyer }
1152b9c00cbSConrad Meyer return diff;
1162b9c00cbSConrad Meyer }
1172b9c00cbSConrad Meyer
UTIL_getSpanTimeMicro(UTIL_time_t begin,UTIL_time_t end)1182b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
1192b9c00cbSConrad Meyer {
1202b9c00cbSConrad Meyer UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
1212b9c00cbSConrad Meyer PTime micro = 0;
1222b9c00cbSConrad Meyer micro += 1000000ULL * diff.tv_sec;
1232b9c00cbSConrad Meyer micro += diff.tv_nsec / 1000ULL;
1242b9c00cbSConrad Meyer return micro;
1252b9c00cbSConrad Meyer }
1262b9c00cbSConrad Meyer
UTIL_getSpanTimeNano(UTIL_time_t begin,UTIL_time_t end)1272b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
1282b9c00cbSConrad Meyer {
1292b9c00cbSConrad Meyer UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
1302b9c00cbSConrad Meyer PTime nano = 0;
1312b9c00cbSConrad Meyer nano += 1000000000ULL * diff.tv_sec;
1322b9c00cbSConrad Meyer nano += diff.tv_nsec;
1332b9c00cbSConrad Meyer return nano;
1342b9c00cbSConrad Meyer }
1352b9c00cbSConrad Meyer
1362b9c00cbSConrad Meyer
1372b9c00cbSConrad Meyer
1382b9c00cbSConrad Meyer #else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */
1392b9c00cbSConrad Meyer
UTIL_getTime(void)1402b9c00cbSConrad Meyer UTIL_time_t UTIL_getTime(void) { return clock(); }
UTIL_getSpanTimeMicro(UTIL_time_t clockStart,UTIL_time_t clockEnd)1412b9c00cbSConrad Meyer PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
UTIL_getSpanTimeNano(UTIL_time_t clockStart,UTIL_time_t clockEnd)1422b9c00cbSConrad Meyer PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
1432b9c00cbSConrad Meyer
1442b9c00cbSConrad Meyer #endif
1452b9c00cbSConrad Meyer
1462b9c00cbSConrad Meyer
1472b9c00cbSConrad Meyer
1482b9c00cbSConrad Meyer /* returns time span in microseconds */
UTIL_clockSpanMicro(UTIL_time_t clockStart)1492b9c00cbSConrad Meyer PTime UTIL_clockSpanMicro(UTIL_time_t clockStart )
1502b9c00cbSConrad Meyer {
1512b9c00cbSConrad Meyer UTIL_time_t const clockEnd = UTIL_getTime();
1522b9c00cbSConrad Meyer return UTIL_getSpanTimeMicro(clockStart, clockEnd);
1532b9c00cbSConrad Meyer }
1542b9c00cbSConrad Meyer
1552b9c00cbSConrad Meyer /* returns time span in microseconds */
UTIL_clockSpanNano(UTIL_time_t clockStart)1562b9c00cbSConrad Meyer PTime UTIL_clockSpanNano(UTIL_time_t clockStart )
1572b9c00cbSConrad Meyer {
1582b9c00cbSConrad Meyer UTIL_time_t const clockEnd = UTIL_getTime();
1592b9c00cbSConrad Meyer return UTIL_getSpanTimeNano(clockStart, clockEnd);
1602b9c00cbSConrad Meyer }
1612b9c00cbSConrad Meyer
UTIL_waitForNextTick(void)1622b9c00cbSConrad Meyer void UTIL_waitForNextTick(void)
1632b9c00cbSConrad Meyer {
1642b9c00cbSConrad Meyer UTIL_time_t const clockStart = UTIL_getTime();
1652b9c00cbSConrad Meyer UTIL_time_t clockEnd;
1662b9c00cbSConrad Meyer do {
1672b9c00cbSConrad Meyer clockEnd = UTIL_getTime();
1682b9c00cbSConrad Meyer } while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
1692b9c00cbSConrad Meyer }
170