gingerBill 3 лет назад
Родитель
Сommit
73cba2cf13

+ 10 - 4
core/sync/sync2/futex_linux.odin

@@ -33,7 +33,7 @@ get_errno :: proc(r: int) -> int {
 	return 0
 }
 
-internal_futex :: proc(f: ^Futex, op: uintptr, val: u32, timeout: rawptr) -> int {
+internal_futex :: proc(f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> int {
 	code := int(intrinsics.syscall(202, uintptr(f), uintptr(op), uintptr(val), uintptr(timeout), 0, 0))
 	return get_errno(code)
 }
@@ -55,13 +55,19 @@ _futex_wait :: proc(f: ^Futex, expected: u32) -> Futex_Error {
 }
 
 _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> Futex_Error {
-	timeout: struct {
+	timespec_t :: struct {
 		tv_sec:  c.long,
 		tv_nsec: c.long,
 	}
 	
-	timeout.tv_sec  = (c.long)(duration/1e9)
-	timeout.tv_nsec = (c.long)(duration%1e9)
+	timeout: timespec_t
+	timeout_ptr: ^timespec_t = nil
+	
+	if duration > 0 {
+		timeout.tv_sec  = (c.long)(duration/1e9)
+		timeout.tv_nsec = (c.long)(duration%1e9)
+		timeout_ptr = &timeout
+	}
 
 	err := internal_futex(f, FUTEX_WAIT_PRIVATE | FUTEX_WAIT, expected, &timeout)
 	switch err {

+ 18 - 9
core/sync/sync2/futex_windows.odin

@@ -5,30 +5,39 @@ package sync2
 import "core:time"
 
 foreign import Synchronization "system:Synchronization.lib"
+foreign import NtDll "system:NtDll.lib"
 
-@(default_calling_convention="c")
+@(default_calling_convention="stdcall")
+foreign NtDll {
+	RtlWaitOnAddress :: proc(Address: rawptr, CompareAddress: rawptr, AddressSize: uint, Timeout: ^i64) -> b32 ---
+}
+
+@(default_calling_convention="stdcall")
 foreign Synchronization {
-	WaitOnAddress :: proc(Address: rawptr, CompareAddress: rawptr, AddressSize: uint, dwMilliseconds: u32) -> b32 ---
 	WakeByAddressSingle :: proc(Address: rawptr) ---
 	WakeByAddressAll :: proc(Address: rawptr) ---
 }
 
+
+
 _futex_wait :: proc(f: ^Futex, expect: u32) -> Futex_Error {
 	expect := expect
-	ms :: ~u32(0) // infinite
-	ok := WaitOnAddress(f, &expect, size_of(expect), ms)
+	ok := RtlWaitOnAddress(f, &expect, size_of(expect), nil)
 	return nil if ok else .Timed_Out
 }
 
 _futex_wait_with_timeout :: proc(f: ^Futex, expect: u32, duration: time.Duration) -> Futex_Error {
 	expect := expect
 	
-	ms: u32 = 0
-	if duration >= 0 {
-		ms = u32(u64(duration)/1e6)
+	timeout: i64
+	timeout_ptr: ^i64
+	if duration > 0 {
+		// In 100 ns units
+		timeout = i64(timeout)/100
+		timeout_ptr = &timeout
 	}
-	
-	ok := WaitOnAddress(f, &expect, size_of(expect), ms)
+	\
+	ok := RtlWaitOnAddress(f, &expect, size_of(expect), timeout_ptr)
 	return nil if ok else .Timed_Out
 }
 

+ 7 - 0
core/sync/sync2/primitives.odin

@@ -153,6 +153,10 @@ cond_wait :: proc(c: ^Cond, m: ^Mutex) {
 	_cond_wait(c, m)
 }
 
+cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
+	return _cond_wait_with_timeout(c, m, duration)
+}
+
 cond_signal :: proc(c: ^Cond) {
 	_cond_signal(c)
 }
@@ -215,6 +219,9 @@ futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duratio
 	if u32(atomic_load(f)) != expected {
 		return nil
 	}
+	if duration == 0 {
+		return .Timed_Out	
+	}	
 	
 	return _futex_wait_with_timeout(f, expected, duration)
 }

+ 7 - 0
core/sync/sync2/primitives_darwin.odin

@@ -3,6 +3,7 @@
 package sync2
 
 import "core:c"
+import "core:time"
 import "core:intrinsics"
 
 foreign import pthread "System.framework"
@@ -43,6 +44,12 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) {
 	atomic_cond_wait(&c.impl.cond, &m.impl.mutex)
 }
 
+_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
+	// TODO(bill): _cond_wait_with_timeout for Darwin
+	atomic_cond_wait(&c.impl.cond, &m.impl.mutex)
+	return true
+}
+
 _cond_signal :: proc(c: ^Cond) {
 	atomic_cond_signal(&c.impl.cond)
 }

+ 10 - 0
core/sync/sync2/primitives_pthreads.odin

@@ -2,6 +2,7 @@
 //+private
 package sync2
 
+import "core:time"
 import "core:sys/unix"
 
 _Mutex_State :: enum i32 {
@@ -37,6 +38,15 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) {
 	assert(err == 0)
 }
 
+
+_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
+	tv_sec  := i64(duration/1e9)
+	tv_nsec := i64(duration%1e9)
+	err := unix.pthread_cond_timedwait(&c.impl.pthread_cond, &m.impl.pthread_mutex, &{tv_sec, tv_nsec})
+	return err == 0
+}
+
+
 _cond_signal :: proc(c: ^Cond) {
 	err := unix.pthread_cond_signal(&c.impl.pthread_cond)
 	assert(err == 0)

+ 8 - 0
core/sync/sync2/primitives_windows.odin

@@ -2,6 +2,7 @@
 //+private
 package sync2
 
+import "core:time"
 import win32 "core:sys/windows"
 
 _current_thread_id :: proc "contextless" () -> int {
@@ -61,6 +62,13 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) {
 	_ = win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, win32.INFINITE, 0)
 }
 
+_cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
+	duration := u32(duration / time.Millisecond)
+	ok := win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, duration, 0)
+	return bool(ok)
+}
+
+
 _cond_signal :: proc(c: ^Cond) {
 	win32.WakeConditionVariable(&c.impl.cond)
 }