diff --git a/core/time/perf.odin b/core/time/perf.odin index 6a9933336..9db667b72 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -6,7 +6,6 @@ import "core:intrinsics" Tick :: struct { _nsec: i64, // relative amount } - tick_now :: proc "contextless" () -> Tick { return _tick_now() } @@ -56,8 +55,38 @@ when ODIN_ARCH == .amd64 { } } +has_invariant_tsc :: proc "contextless" () -> bool { + when ODIN_ARCH == .amd64 { + return x86_has_invariant_tsc() + } + + return false +} + +_get_tsc_frequency_fallback :: proc "contextless" () -> u64 { + tsc_begin := intrinsics.read_cycle_counter() + tick_begin := tick_now() + + sleep(2 * Second) + + tsc_end := intrinsics.read_cycle_counter() + tick_end := tick_now() + + time_diff := u128(duration_nanoseconds(tick_diff(tick_begin, tick_end))) + return u64((u128(tsc_end - tsc_begin) * 1_000_000_000) / time_diff) +} + get_tsc_frequency :: proc "contextless" () -> (u64, bool) { - return _get_tsc_frequency() + if !has_invariant_tsc() { + return 0, false + } + + hz, ok := _get_tsc_frequency() + if !ok { + hz = _get_tsc_frequency_fallback() + } + + return hz, true } /* diff --git a/core/time/tsc_freebsd.odin b/core/time/tsc_freebsd.odin new file mode 100644 index 000000000..f4d6ccc3a --- /dev/null +++ b/core/time/tsc_freebsd.odin @@ -0,0 +1,21 @@ +//+private +//+build freebsd +package time + +import "core:c" + +foreign import libc "system:c" +foreign libc { + @(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int --- +} + +_get_tsc_frequency :: proc "contextless" () -> (u64, bool) { + tmp_freq : u64 = 0 + tmp_size : i64 = size_of(tmp_freq) + ret := _sysctlbyname("machdep.tsc_freq", &tmp_freq, &tmp_size, nil, 0) + if ret < 0 { + return 0, false + } + + return tmp_freq, true +} diff --git a/core/time/tsc_openbsd.odin b/core/time/tsc_openbsd.odin new file mode 100644 index 000000000..ab126d5c1 --- /dev/null +++ b/core/time/tsc_openbsd.odin @@ -0,0 +1,7 @@ +//+private +//+build openbsd +package time + +_get_tsc_frequency :: proc "contextless" () -> (u64, bool) { + return 0, false +} diff --git a/core/time/tsc_windows.odin b/core/time/tsc_windows.odin index a1707f982..7f7be6393 100644 --- a/core/time/tsc_windows.odin +++ b/core/time/tsc_windows.odin @@ -2,23 +2,6 @@ //+build windows package time -import "core:intrinsics" -import win32 "core:sys/windows" - _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { - qpc_begin: win32.LARGE_INTEGER - win32.QueryPerformanceCounter(&qpc_begin) - tsc_begin := intrinsics.read_cycle_counter() - - win32.Sleep(2) - - qpc_end: win32.LARGE_INTEGER - win32.QueryPerformanceCounter(&qpc_end) - tsc_end := intrinsics.read_cycle_counter() - - qpc_frequency: win32.LARGE_INTEGER - win32.QueryPerformanceFrequency(&qpc_frequency) - - frequency = u64((u128(tsc_end - tsc_begin) * u128(qpc_frequency)) / u128(qpc_end - qpc_begin)) - return frequency, true + return 0, false }