Commit 43900011f7
Changed files (1)
lib
std
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;
};