authorgravatar for kbutcher6200@gmail.comkprotty <kbutcher6200@gmail.com> 2019-11-07 18:56:43-06:00
committergravatar for kbutcher6200@gmail.comkprotty <kbutcher6200@gmail.com> 2019-11-07 18:56:43-06:00
log43900011f7379e61564196141a687a2b8352d27f
tree2214e2bee5111fc51aaac7bf8aa7d8a8c655e56f
parentfe8c1cf804c3c39e57ca291baf005b862fc3ba94

handle NtCreateKeyedEvent failure by spinning to ensure correctness


1 files changed, 15 insertions(+), 8 deletions(-)

lib/std/parker.zig+15-8
......@@ -1,5 +1,6 @@
11const std = @import("std.zig");
22const builtin = @import("builtin");
3const time = std.time;
34const testing = std.testing;
45const assert = std.debug.assert;
56const SpinLock = std.SpinLock;
......@@ -76,12 +77,13 @@ const WindowsParker = struct {
7677 pub fn deinit(self: *WindowsParker) void {}
7778
7879 pub fn unpark(self: *WindowsParker, ptr: *const u32) void {
79 const handle = getEventHandlePtr().*;
8080 const key = @ptrCast(*const c_void, ptr);
81 const handle_ptr = getEventHandlePtr() orelse return;
82
8183 var waiting = @atomicLoad(u32, &self.waiters, .Monotonic);
8284 while (waiting != 0) {
8385 waiting = @cmpxchgWeak(u32, &self.waiters, waiting, waiting - 1, .Acquire, .Monotonic) orelse {
84 const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null);
86 const rc = windows.ntdll.NtReleaseKeyedEvent(handle_ptr.*, key, windows.FALSE, null);
8587 assert(rc == 0);
8688 return;
8789 };
......@@ -89,22 +91,27 @@ const WindowsParker = struct {
8991 }
9092
9193 pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void {
92 const handle = getEventHandlePtr().*;
94 var spin = SpinLock.Backoff.init();
9395 const key = @ptrCast(*const c_void, ptr);
96
9497 while (@atomicLoad(u32, ptr, .Acquire) == expected) {
95 _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release);
96 const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null);
97 assert(rc == 0);
98 if (getEventHandlePtr()) |handle_ptr| {
99 _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release);
100 const rc = windows.ntdll.NtWaitForKeyedEvent(handle_ptr.*, key, windows.FALSE, null);
101 assert(rc == 0);
102 } else {
103 spin.yield();
104 }
98105 }
99106 }
100107
101108 var event_handle = std.lazyInit(windows.HANDLE);
102109
103 fn getEventHandlePtr() *const windows.HANDLE {
110 fn getEventHandlePtr() ?*const windows.HANDLE {
104111 return event_handle.get() orelse {
105112 const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE;
106113 if (windows.ntdll.NtCreateKeyedEvent(&event_handle.data, access_mask, null, 0) != 0)
107 @panic("Failed to setup an NT Keyed Event handle for the process");
114 return null;
108115 event_handle.resolve();
109116 return &event_handle.data;
110117 };