From 82765ca96e90f8ca3d2870e1b00bba3fecc0a78f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 17 Aug 2022 13:12:45 +0100 Subject: [PATCH] Fix `RtlWaitOnAddress` behaviour with `SetLastError(RtlNtStatusToDosError(status))` if an error occurred --- core/sync/futex_windows.odin | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/core/sync/futex_windows.odin b/core/sync/futex_windows.odin index ce662ba9e..ba6292742 100644 --- a/core/sync/futex_windows.odin +++ b/core/sync/futex_windows.odin @@ -15,18 +15,40 @@ foreign import Ntdll "system:Ntdll.lib" @(default_calling_convention="stdcall") foreign Ntdll { RtlWaitOnAddress :: proc(Address: rawptr, CompareAddress: rawptr, AddressSize: uint, Timeout: ^i64) -> i32 --- + RtlNtStatusToDosError :: proc(status: i32) -> u32 --- + SetLastError :: proc(err: u32) --- } + +/* + NOTE(bill, 2022-08-17) + WaitOnAddress is implemented on top of RtlWaitOnAddress + BUT requires taking the return value of it and if it is non-zero + converting that status to a DOS error and then SetLastError + If this is not done, then things don't work as expected when + and error occurs + + GODDAMN MICROSOFT! +*/ +CustomWaitOnAddress :: proc "stdcall" (Address: rawptr, CompareAddress: rawptr, AddressSize: uint, Timeout: ^i64) -> bool { + status := RtlWaitOnAddress(Address, CompareAddress, AddressSize, Timeout) + if status != 0 { + SetLastError(RtlNtStatusToDosError(status)) + } + return status == 0 +} + + _futex_wait :: proc(f: ^Futex, expect: u32) -> bool { expect := expect - return 0 == RtlWaitOnAddress(f, &expect, size_of(expect), nil) + return CustomWaitOnAddress(f, &expect, size_of(expect), nil) } _futex_wait_with_timeout :: proc(f: ^Futex, expect: u32, duration: time.Duration) -> bool { expect := expect // NOTE(bill): for some bizarre reason, this has be a negative number timeout := -i64(duration / 100) - return 0 == RtlWaitOnAddress(f, &expect, size_of(expect), &timeout) + return CustomWaitOnAddress(f, &expect, size_of(expect), &timeout) } _futex_signal :: proc(f: ^Futex) {