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 | |
8 | namespace duckdb { |
9 | |
10 | inline 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 | |
17 | inline 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 | } |
73 | uint64_t CycleCounter::Tick() const { |
74 | return Now(); |
75 | } |
76 | } // namespace duckdb |
77 | |