diff options
| author | Colin Davidson <colrdavidson@gmail.com> | 2023-02-21 17:48:49 -0800 |
|---|---|---|
| committer | Colin Davidson <colrdavidson@gmail.com> | 2023-02-21 17:48:49 -0800 |
| commit | 8e5e43f335e0a522c97a67de57bd909a669edca0 (patch) | |
| tree | daa9d46bd762c056a59b3ec5294d1dd1cf503698 | |
| parent | 91dccf8d6240e140f96b3ea29bd9b3fc1e69734c (diff) | |
add sleep-fallback and invariant check
| -rw-r--r-- | core/time/perf.odin | 33 | ||||
| -rw-r--r-- | core/time/tsc_freebsd.odin | 21 | ||||
| -rw-r--r-- | core/time/tsc_openbsd.odin | 7 | ||||
| -rw-r--r-- | core/time/tsc_windows.odin | 19 |
4 files changed, 60 insertions, 20 deletions
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 } |