1// This file is licensed under Apache License 2.0
2// Source code taken from https://github.com/google/benchmark
3// It is highly modified
4
5#include "duckdb/common/cycle_counter.hpp"
6#include "duckdb/common/chrono.hpp"
7
8namespace duckdb {
9
10inline uint64_t ChronoNow() {
11 return std::chrono::duration_cast<std::chrono::nanoseconds>(
12 d: std::chrono::time_point_cast<std::chrono::nanoseconds>(t: std::chrono::high_resolution_clock::now())
13 .time_since_epoch())
14 .count();
15}
16
17inline uint64_t Now() {
18#if defined(RDTSC)
19#if defined(__i386__)
20 uint64_t ret;
21 __asm__ volatile("rdtsc" : "=A"(ret));
22 return ret;
23#elif defined(__x86_64__) || defined(__amd64__)
24 uint64_t low, high;
25 __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
26 return (high << 32) | low;
27#elif defined(__powerpc__) || defined(__ppc__)
28 uint64_t tbl, tbu0, tbu1;
29 asm("mftbu %0" : "=r"(tbu0));
30 asm("mftb %0" : "=r"(tbl));
31 asm("mftbu %0" : "=r"(tbu1));
32 tbl &= -static_cast<int64>(tbu0 == tbu1);
33 return (tbu1 << 32) | tbl;
34#elif defined(__sparc__)
35 uint64_t tick;
36 asm(".byte 0x83, 0x41, 0x00, 0x00");
37 asm("mov %%g1, %0" : "=r"(tick));
38 return tick;
39#elif defined(__ia64__)
40 uint64_t itc;
41 asm("mov %0 = ar.itc" : "=r"(itc));
42 return itc;
43#elif defined(COMPILER_MSVC) && defined(_M_IX86)
44 _asm rdtsc
45#elif defined(COMPILER_MSVC)
46 return __rdtsc();
47#elif defined(__aarch64__)
48 uint64_t virtual_timer_value;
49 asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
50 return virtual_timer_value;
51#elif defined(__ARM_ARCH)
52#if (__ARM_ARCH >= 6)
53 uint32_t pmccntr;
54 uint32_t pmuseren;
55 uint32_t pmcntenset;
56 asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
57 if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
58 asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
59 if (pmcntenset & 0x80000000ul) { // Is it counting?
60 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
61 return static_cast<uint64_t>(pmccntr) * 64; // Should optimize to << 6
62 }
63 }
64#endif
65 return ChronoNow();
66#else
67 return ChronoNow();
68#endif
69#else
70 return ChronoNow();
71#endif // defined(RDTSC)
72}
73uint64_t CycleCounter::Tick() const {
74 return Now();
75}
76} // namespace duckdb
77