From a0955990dc2c8df42879e33b308ca177ba2c771a Mon Sep 17 00:00:00 2001 From: kprotty Date: Sat, 23 Nov 2019 15:50:08 -0600 Subject: [PATCH] fix ResetEvent windows bugs --- lib/std/reset_event.zig | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/std/reset_event.zig b/lib/std/reset_event.zig index 59399d5e78..f3194b0a7d 100644 --- a/lib/std/reset_event.zig +++ b/lib/std/reset_event.zig @@ -219,17 +219,23 @@ const WindowsEvent = AtomicEvent(struct { return SpinEvent.Futex.wait(ptr, expected, timeout); }; + // NT uses timeouts in units of 100ns with negative value being relative var timeout_ptr: ?*windows.LARGE_INTEGER = null; var timeout_value: windows.LARGE_INTEGER = undefined; if (timeout) |timeout_ns| { timeout_ptr = &timeout_value; - timeout_value = @intCast(windows.LARGE_INTEGER, @divFloor(timeout_ns, time.millisecond)); + timeout_value = -@intCast(windows.LARGE_INTEGER, timeout_ns / 100); } - const key = @ptrCast(*const c_void, ptr); - while (@atomicLoad(u32, ptr, .Acquire) == expected) { + // NtWaitForKeyedEvent doesnt have spurious wake-ups + if (@atomicLoad(u32, ptr, .Acquire) == expected) { + const key = @ptrCast(*const c_void, ptr); const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, timeout_ptr); - assert(rc == 0); + switch (rc) { + 0 => {}, + windows.WAIT_TIMEOUT => return ResetEvent.WaitError.TimedOut, + else => unreachable, + } } } @@ -377,10 +383,13 @@ test "std.ResetEvent" { // test waiting timeout const delay = 100 * time.millisecond; + const error_margin = 50 * time.millisecond; + var timer = time.Timer.start() catch unreachable; testing.expectError(ResetEvent.WaitError.TimedOut, event.wait(delay)); const elapsed = timer.read(); - testing.expect(elapsed >= delay and elapsed < delay * 2); + testing.expect(elapsed >= delay - error_margin); + testing.expect(elapsed <= delay + error_margin); // test cross thread signaling const Context = struct {