Commit a0955990dc

kprotty <kbutcher6200@gmail.com>
2019-11-23 22:50:08
fix ResetEvent windows bugs
1 parent ef208fe
Changed files (1)
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 {