From 43900011f7379e61564196141a687a2b8352d27f Mon Sep 17 00:00:00 2001 From: kprotty Date: Thu, 7 Nov 2019 18:56:43 -0600 Subject: [PATCH] handle NtCreateKeyedEvent failure by spinning to ensure correctness --- lib/std/parker.zig | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/std/parker.zig b/lib/std/parker.zig index 7c0a7a65f8..11d3f749de 100644 --- a/lib/std/parker.zig +++ b/lib/std/parker.zig @@ -1,5 +1,6 @@ const std = @import("std.zig"); const builtin = @import("builtin"); +const time = std.time; const testing = std.testing; const assert = std.debug.assert; const SpinLock = std.SpinLock; @@ -76,12 +77,13 @@ const WindowsParker = struct { pub fn deinit(self: *WindowsParker) void {} pub fn unpark(self: *WindowsParker, ptr: *const u32) void { - const handle = getEventHandlePtr().*; const key = @ptrCast(*const c_void, ptr); + const handle_ptr = getEventHandlePtr() orelse return; + var waiting = @atomicLoad(u32, &self.waiters, .Monotonic); while (waiting != 0) { waiting = @cmpxchgWeak(u32, &self.waiters, waiting, waiting - 1, .Acquire, .Monotonic) orelse { - const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null); + const rc = windows.ntdll.NtReleaseKeyedEvent(handle_ptr.*, key, windows.FALSE, null); assert(rc == 0); return; }; @@ -89,22 +91,27 @@ const WindowsParker = struct { } pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void { - const handle = getEventHandlePtr().*; + var spin = SpinLock.Backoff.init(); const key = @ptrCast(*const c_void, ptr); + while (@atomicLoad(u32, ptr, .Acquire) == expected) { - _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release); - const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null); - assert(rc == 0); + if (getEventHandlePtr()) |handle_ptr| { + _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release); + const rc = windows.ntdll.NtWaitForKeyedEvent(handle_ptr.*, key, windows.FALSE, null); + assert(rc == 0); + } else { + spin.yield(); + } } } var event_handle = std.lazyInit(windows.HANDLE); - fn getEventHandlePtr() *const windows.HANDLE { + fn getEventHandlePtr() ?*const windows.HANDLE { return event_handle.get() orelse { const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE; if (windows.ntdll.NtCreateKeyedEvent(&event_handle.data, access_mask, null, 0) != 0) - @panic("Failed to setup an NT Keyed Event handle for the process"); + return null; event_handle.resolve(); return &event_handle.data; };