authorgravatar for kbutcher6200@gmail.comkprotty <kbutcher6200@gmail.com> 2019-11-07 15:46:57-06:00
committergravatar for kbutcher6200@gmail.comkprotty <kbutcher6200@gmail.com> 2019-11-07 15:46:57-06:00
logb5d84635f20a891cea55174771b630099bb3860d
tree6b761c4684a1ef6a2ee16dcb31e5de1060a86eaf
parentb535e86cc0e86e76471aebd731566ae140098a07

remove WaitOnAddress backend in std.ThreadParker


2 files changed, 24 insertions(+), 96 deletions(-)

lib/std/os/windows/kernel32.zig-4
......@@ -82,8 +82,6 @@ pub extern "kernel32" stdcallcc fn GetFileAttributesW(lpFileName: [*]const WCHAR
8282
8383pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) DWORD;
8484
85pub extern "kernel32" stdcallcc fn GetModuleHandleA(lpModuleName: ?[*]const CHAR) ?HMODULE;
86
8785pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) HMODULE;
8886
8987pub extern "kernel32" stdcallcc fn GetLastError() DWORD;
......@@ -206,8 +204,6 @@ pub extern "kernel32" stdcallcc fn WriteFile(
206204
207205pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const u8, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;
208206
209pub extern "kernel32" stdcallcc fn LoadLibraryA(lpLibFileName: [*]const u8) ?HMODULE;
210
211207pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
212208
213209pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;
lib/std/parker.zig+24-92
......@@ -76,107 +76,39 @@ const WindowsParker = struct {
7676 pub fn deinit(self: *WindowsParker) void {}
7777
7878 pub fn unpark(self: *WindowsParker, ptr: *const u32) void {
79 switch (Backend.get().*) {
80 .WaitAddress => |*backend| backend.unpark(ptr, &self.waiters),
81 .KeyedEvent => |*backend| backend.unpark(ptr, &self.waiters),
79 const handle = getEventHandlePtr().*;
80 const key = @ptrCast(*const c_void, ptr);
81 var waiting = @atomicLoad(u32, &self.waiters, .Monotonic);
82 while (waiting != 0) {
83 waiting = @cmpxchgWeak(u32, &self.waiters, waiting, waiting - 1, .Acquire, .Monotonic) orelse {
84 const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null);
85 assert(rc == 0);
86 return;
87 };
8288 }
8389 }
8490
8591 pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void {
86 switch (Backend.get().*) {
87 .WaitAddress => |*backend| backend.park(ptr, expected, &self.waiters),
88 .KeyedEvent => |*backend| backend.park(ptr, expected, &self.waiters),
92 const handle = getEventHandlePtr().*;
93 const key = @ptrCast(*const c_void, ptr);
94 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);
8998 }
9099 }
91100
92 const Backend = union(enum) {
93 WaitAddress: WaitAddress,
94 KeyedEvent: KeyedEvent,
95
96 var backend = std.lazyInit(Backend);
97
98 fn get() *const Backend {
99 return backend.get() orelse {
100 // Statically linking to the KeyedEvent functions should mean its supported.
101 // TODO: Maybe add a CreateSemaphore backend for systems older than Windows XP ?
102 backend.data = WaitAddress.init()
103 orelse KeyedEvent.init()
104 orelse unreachable;
105 backend.resolve();
106 return &backend.data;
107 };
108 }
109
110 const WaitAddress = struct {
111 WakeByAddressSingle: stdcallcc fn(Address: *const c_void) void,
112 WaitOnAddress: stdcallcc fn (
113 Address: *const c_void,
114 CompareAddress: *const c_void,
115 AddressSize: windows.SIZE_T,
116 dwMilliseconds: windows.DWORD,
117 ) windows.BOOL,
118
119 fn init() ?Backend {
120 const dll_name = c"api-ms-win-core-synch-l1-2-0";
121 const dll = windows.kernel32.GetModuleHandleA(dll_name)
122 orelse windows.kernel32.LoadLibraryA(dll_name)
123 orelse return null;
124
125 var self: WaitAddress = undefined;
126 const WaitOnAddress = windows.kernel32.GetProcAddress(dll, c"WaitOnAddress") orelse return null;
127 self.WaitOnAddress = @intToPtr(@typeOf(self.WaitOnAddress), @ptrToInt(WaitOnAddress));
128 const WakeByAddressSingle = windows.kernel32.GetProcAddress(dll, c"WakeByAddressSingle") orelse return null;
129 self.WakeByAddressSingle = @intToPtr(@typeOf(self.WakeByAddressSingle), @ptrToInt(WakeByAddressSingle));
130 return Backend{ .WaitAddress = self };
131 }
132
133 fn unpark(self: WaitAddress, ptr: *const u32, waiters: *u32) void {
134 const addr = @ptrCast(*const c_void, ptr);
135 self.WakeByAddressSingle(addr);
136 }
101 var event_handle = std.lazyInit(windows.HANDLE);
137102
138 fn park(self: WaitAddress, ptr: *const u32, expected: u32, waiters: *u32) void {
139 var compare = expected;
140 const addr = @ptrCast(*const c_void, ptr);
141 const cmp = @ptrCast(*const c_void, &compare);
142 while (@atomicLoad(u32, ptr, .Acquire) == expected)
143 _ = self.WaitOnAddress(addr, cmp, @sizeOf(u32), windows.INFINITE);
144 }
103 fn getEventHandlePtr() *const windows.HANDLE {
104 return event_handle.get() orelse {
105 const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE;
106 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");
108 event_handle.resolve();
109 return &event_handle.data;
145110 };
146
147 const KeyedEvent = struct {
148 handle: windows.HANDLE,
149
150 fn init() ?Backend {
151 var self: KeyedEvent = undefined;
152 const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE;
153 if (windows.ntdll.NtCreateKeyedEvent(&self.handle, access_mask, null, 0) != 0)
154 return null;
155 return Backend{ .KeyedEvent = self };
156 }
157
158 fn unpark(self: KeyedEvent, ptr: *const u32, waiters: *u32) void {
159 const key = @ptrCast(*const c_void, ptr);
160 var waiting = @atomicLoad(u32, waiters, .Acquire);
161 while (waiting != 0) {
162 waiting = @cmpxchgWeak(u32, waiters, waiting, waiting - 1, .Acquire, .Monotonic) orelse {
163 const rc = windows.ntdll.NtReleaseKeyedEvent(self.handle, key, windows.FALSE, null);
164 assert(rc == 0);
165 return;
166 };
167 }
168 }
169
170 fn park(self: KeyedEvent, ptr: *const u32, expected: u32, waiters: *u32) void {
171 const key = @ptrCast(*const c_void, ptr);
172 while (@atomicLoad(u32, ptr, .Acquire) == expected) {
173 _ = @atomicRmw(u32, waiters, .Add, 1, .Release);
174 const rc = windows.ntdll.NtWaitForKeyedEvent(self.handle, key, windows.FALSE, null);
175 assert(rc == 0);
176 }
177 }
178 };
179 };
111 }
180112};
181113
182114const PosixParker = struct {