aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Davidson <colrdavidson@gmail.com>2023-02-21 17:48:49 -0800
committerColin Davidson <colrdavidson@gmail.com>2023-02-21 17:48:49 -0800
commit8e5e43f335e0a522c97a67de57bd909a669edca0 (patch)
treedaa9d46bd762c056a59b3ec5294d1dd1cf503698
parent91dccf8d6240e140f96b3ea29bd9b3fc1e69734c (diff)
add sleep-fallback and invariant check
-rw-r--r--core/time/perf.odin33
-rw-r--r--core/time/tsc_freebsd.odin21
-rw-r--r--core/time/tsc_openbsd.odin7
-rw-r--r--core/time/tsc_windows.odin19
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
}