Browse Source

time: yield accurate_sleep instead of relaxing the cpu

hikari 3 years ago
parent
commit
0a0440a6e8
3 changed files with 18 additions and 2 deletions
  1. 8 2
      core/time/time.odin
  2. 6 0
      core/time/time_unix.odin
  3. 4 0
      core/time/time_windows.odin

+ 8 - 2
core/time/time.odin

@@ -213,6 +213,10 @@ time_add :: proc(t: Time, d: Duration) -> Time {
 	return Time{t._nsec + i64(d)}
 }
 
+yield :: proc "contextless" () {
+	_yield()
+}
+
 // Accurate sleep borrowed from: https://blat-blatnik.github.io/computerBear/making-accurate-sleep-function/
 accurate_sleep :: proc(d: Duration) {
 	to_sleep, estimate, mean, m2, count: Duration
@@ -240,8 +244,10 @@ accurate_sleep :: proc(d: Duration) {
 
 	start := tick_now()
 	for to_sleep > tick_since(start) {
-		intrinsics.cpu_relax() // prevent the spinlock from taking the thread hostage, still accurate enough
-		// NOTE: it is possible that sometimes cpu can relax a bit too much, in that case it should spinlock freely for a while (TODO)
+		// prevent the spinlock from taking the thread hostage, still accurate enough
+		yield()
+		// NOTE: it might be possible that it yields for too long, in that case it should spinlock freely for a while
+		// TODO: needs actual testing done to check if that's the case
 	}
 }
 

+ 6 - 0
core/time/time_unix.odin

@@ -1,6 +1,8 @@
 //+build linux, darwin, freebsd, openbsd
 package time
 
+import "core:sys/unix"
+
 IS_SUPPORTED :: true // NOTE: Times on Darwin are UTC.
 
 when ODIN_OS == .Darwin {
@@ -17,6 +19,10 @@ foreign libc {
 	@(link_name="nanosleep")     _unix_nanosleep     :: proc(requested: ^TimeSpec, remaining: ^TimeSpec) -> i32 ---
 }
 
+_yield :: proc "contextless" () {
+	unix.sched_yield()
+}
+
 TimeSpec :: struct {
 	tv_sec  : i64,  /* seconds */
 	tv_nsec : i64,  /* nanoseconds */

+ 4 - 0
core/time/time_windows.odin

@@ -35,3 +35,7 @@ _tick_now :: proc "contextless" () -> Tick {
 	_nsec := mul_div_u64(i64(now), 1e9, i64(qpc_frequency))
 	return Tick{_nsec = _nsec}
 }
+
+_yield :: proc "contextless" () {
+	win32.SwitchToThread()
+}