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 @@...@@ -1,5 +1,6 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const time = std.time;
3const testing = std.testing;4const testing = std.testing;
4const assert = std.debug.assert;5const assert = std.debug.assert;
5const SpinLock = std.SpinLock;6const SpinLock = std.SpinLock;
...@@ -76,12 +77,13 @@ const WindowsParker = struct {...@@ -76,12 +77,13 @@ const WindowsParker = struct {
76 pub fn deinit(self: *WindowsParker) void {}77 pub fn deinit(self: *WindowsParker) void {}
7778
78 pub fn unpark(self: *WindowsParker, ptr: *const u32) void {79 pub fn unpark(self: *WindowsParker, ptr: *const u32) void {
79 const handle = getEventHandlePtr().*;
80 const key = @ptrCast(*const c_void, ptr);80 const key = @ptrCast(*const c_void, ptr);
81 const handle_ptr = getEventHandlePtr() orelse return;
82
81 var waiting = @atomicLoad(u32, &self.waiters, .Monotonic);83 var waiting = @atomicLoad(u32, &self.waiters, .Monotonic);
82 while (waiting != 0) {84 while (waiting != 0) {
83 waiting = @cmpxchgWeak(u32, &self.waiters, waiting, waiting - 1, .Acquire, .Monotonic) orelse {85 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);
85 assert(rc == 0);87 assert(rc == 0);
86 return;88 return;
87 };89 };
...@@ -89,22 +91,27 @@ const WindowsParker = struct {...@@ -89,22 +91,27 @@ const WindowsParker = struct {
89 }91 }
9092
91 pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void {93 pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void {
92 const handle = getEventHandlePtr().*;94 var spin = SpinLock.Backoff.init();
93 const key = @ptrCast(*const c_void, ptr);95 const key = @ptrCast(*const c_void, ptr);
96
94 while (@atomicLoad(u32, ptr, .Acquire) == expected) {97 while (@atomicLoad(u32, ptr, .Acquire) == expected) {
95 _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release);98 if (getEventHandlePtr()) |handle_ptr| {
96 const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null);99 _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release);
97 assert(rc == 0);100 const rc = windows.ntdll.NtWaitForKeyedEvent(handle_ptr.*, key, windows.FALSE, null);
101 assert(rc == 0);
102 } else {
103 spin.yield();
104 }
98 }105 }
99 }106 }
100107
101 var event_handle = std.lazyInit(windows.HANDLE);108 var event_handle = std.lazyInit(windows.HANDLE);
102109
103 fn getEventHandlePtr() *const windows.HANDLE {110 fn getEventHandlePtr() ?*const windows.HANDLE {
104 return event_handle.get() orelse {111 return event_handle.get() orelse {
105 const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE;112 const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE;
106 if (windows.ntdll.NtCreateKeyedEvent(&event_handle.data, access_mask, null, 0) != 0)113 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;
108 event_handle.resolve();115 event_handle.resolve();
109 return &event_handle.data;116 return &event_handle.data;
110 };117 };