#ifndef _XKCP_timing_h_
#define _XKCP_timing_h_
#include <stdint.h>
#if defined(__GNUC__)
#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
#elif defined(_MSC_VER) && !defined(__clang__)
#define BENCHMARK_ALWAYS_INLINE __forceinline
#if _MSC_VER >= 1900
#else
#endif
#define __func__ __FUNCTION__
#else
#define BENCHMARK_ALWAYS_INLINE
#endif
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#if defined(__clang__)
#if defined(__ibmxl__)
#if !defined(COMPILER_IBMXL)
#define COMPILER_IBMXL
#endif
#elif !defined(COMPILER_CLANG)
#define COMPILER_CLANG
#endif
#elif defined(_MSC_VER)
#if !defined(COMPILER_MSVC)
#define COMPILER_MSVC
#endif
#elif defined(__GNUC__)
#if !defined(COMPILER_GCC)
#define COMPILER_GCC
#endif
#endif
#if defined(__CYGWIN__)
#define BENCHMARK_OS_CYGWIN 1
#elif defined(_WIN32)
#define BENCHMARK_OS_WINDOWS 1
#if defined(__MINGW32__)
#define BENCHMARK_OS_MINGW 1
#endif
#elif defined(__APPLE__)
#define BENCHMARK_OS_APPLE 1
#include "TargetConditionals.h"
#if defined(TARGET_OS_MAC)
#define BENCHMARK_OS_MACOSX 1
#if defined(TARGET_OS_IPHONE)
#define BENCHMARK_OS_IOS 1
#endif
#endif
#elif defined(__FreeBSD__)
#define BENCHMARK_OS_FREEBSD 1
#elif defined(__NetBSD__)
#define BENCHMARK_OS_NETBSD 1
#elif defined(__OpenBSD__)
#define BENCHMARK_OS_OPENBSD 1
#elif defined(__DragonFly__)
#define BENCHMARK_OS_DRAGONFLY 1
#elif defined(__linux__)
#define BENCHMARK_OS_LINUX 1
#elif defined(__native_client__)
#define BENCHMARK_OS_NACL 1
#elif defined(__EMSCRIPTEN__)
#define BENCHMARK_OS_EMSCRIPTEN 1
#elif defined(__rtems__)
#define BENCHMARK_OS_RTEMS 1
#elif defined(__Fuchsia__)
#define BENCHMARK_OS_FUCHSIA 1
#elif defined (__SVR4) && defined (__sun)
#define BENCHMARK_OS_SOLARIS 1
#elif defined(__QNX__)
#define BENCHMARK_OS_QNX 1
#elif defined(__MVS__)
#define BENCHMARK_OS_ZOS 1
#endif
#if defined(BENCHMARK_OS_MACOSX)
#include <mach/mach_time.h>
#endif
#if defined(COMPILER_MSVC) && !defined(_M_IX86)
uint64_t __rdtsc();
#pragma intrinsic(__rdtsc)
#endif
#if !defined(BENCHMARK_OS_WINDOWS) || defined(BENCHMARK_OS_MINGW)
#include <sys/time.h>
#include <time.h>
#endif
#ifdef BENCHMARK_OS_EMSCRIPTEN
#include <emscripten.h>
#endif
inline BENCHMARK_ALWAYS_INLINE int64_t CycleTimer() {
#if defined(BENCHMARK_OS_EMSCRIPTEN)
return (int64_t)(emscripten_get_now() * 1e+6);
#elif defined(__i386__)
int64_t ret;
__asm__ volatile("rdtsc" : "=A"(ret));
return ret;
#elif defined(__x86_64__) || defined(__amd64__)
uint64_t low, high;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
return (high << 32) | low;
#elif defined(BENCHMARK_OS_MACOSX)
return mach_absolute_time();
#elif defined(__powerpc__) || defined(__ppc__)
#if defined(__powerpc64__) || defined(__ppc64__)
int64_t tb;
asm volatile("mfspr %0, 268" : "=r"(tb));
return tb;
#else
uint32_t tbl, tbu0, tbu1;
asm volatile(
"mftbu %0\n"
"mftb %1\n"
"mftbu %2"
: "=r"(tbu0), "=r"(tbl), "=r"(tbu1));
tbl &= -(int32_t)(tbu0 == tbu1);
return ((uint64_t)(tbu1) << 32) | tbl;
#endif
#elif defined(__sparc__)
int64_t tick;
asm(".byte 0x83, 0x41, 0x00, 0x00");
asm("mov %%g1, %0" : "=r"(tick));
return tick;
#elif defined(__ia64__)
int64_t itc;
asm("mov %0 = ar.itc" : "=r"(itc));
return itc;
#elif defined(COMPILER_MSVC) && defined(_M_IX86)
_asm rdtsc
#elif defined(COMPILER_MSVC)
return __rdtsc();
#elif defined(BENCHMARK_OS_NACL)
struct timespec ts = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)(ts.tv_sec) * 1000000000 + ts.tv_nsec;
#elif defined(__aarch64__)
int64_t virtual_timer_value;
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
return virtual_timer_value;
#elif defined(__ARM_ARCH)
#if (__ARM_ARCH >= 6)
uint32_t pmccntr;
uint32_t pmuseren;
uint32_t pmcntenset;
asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
if (pmuseren & 1) { asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
if (pmcntenset & 0x80000000ul) { asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
return (int64_t)(pmccntr) * 64; }
}
#endif
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#elif defined(__mips__) || defined(__m68k__)
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#elif defined(__s390__)
uint64_t tsc;
#if defined(BENCHMARK_OS_ZOS) && defined(COMPILER_IBMXL)
asm(" stck %0" : "=m"(tsc) : : "cc");
#else
asm("stck %0" : "=Q"(tsc) : : "cc");
#endif
return tsc;
#elif defined(__riscv)
#if __riscv_xlen == 32
uint32_t cycles_lo, cycles_hi0, cycles_hi1;
asm volatile(
"rdcycleh %0\n"
"rdcycle %1\n"
"rdcycleh %2\n"
"sub %0, %0, %2\n"
"seqz %0, %0\n"
"sub %0, zero, %0\n"
"and %1, %1, %0\n"
: "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
return ((uint64_t)(cycles_hi1) << 32) | cycles_lo;
#else
uint64_t cycles;
asm volatile("rdcycle %0" : "=r"(cycles));
return cycles;
#endif
#else
#error You need to define CycleTimer for your OS and CPU
#endif
}
typedef int64_t cycles_t;
#define CYCLES_MAX INT64_MAX
#define TIMER_SAMPLE_CNT (100)
const char * getTimerUnit();
extern double timerCorrectionFactor;
cycles_t CalibrateTimer();
#define measureTimingDeclare \
cycles_t tMin = CYCLES_MAX; \
cycles_t t0,t1,i;
#define measureTimingBeginDeclared \
for (i=0;i < TIMER_SAMPLE_CNT;i++) \
{ \
t0 = CycleTimer();
#define measureTimingBegin \
cycles_t tMin = CYCLES_MAX; \
cycles_t t0,t1,i; \
for (i=0;i < TIMER_SAMPLE_CNT;i++) \
{ \
t0 = CycleTimer();
#define measureTimingEnd \
t1 = CycleTimer(); \
if (tMin > t1-t0 - dtMin) \
tMin = t1-t0 - dtMin; \
} \
return (cycles_t)(tMin * timerCorrectionFactor + 0.5);
#endif