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...@@ -82,8 +82,6 @@ pub extern "kernel32" stdcallcc fn GetFileAttributesW(lpFileName: [*]const WCHAR
8282
83pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) DWORD;83pub extern "kernel32" stdcallcc fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u16, nSize: DWORD) DWORD;
8484
85pub extern "kernel32" stdcallcc fn GetModuleHandleA(lpModuleName: ?[*]const CHAR) ?HMODULE;
86
87pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) HMODULE;85pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHAR) HMODULE;
8886
89pub extern "kernel32" stdcallcc fn GetLastError() DWORD;87pub extern "kernel32" stdcallcc fn GetLastError() DWORD;
...@@ -206,8 +204,6 @@ pub extern "kernel32" stdcallcc fn WriteFile(...@@ -206,8 +204,6 @@ pub extern "kernel32" stdcallcc fn WriteFile(
206204
207pub extern "kernel32" stdcallcc fn WriteFileEx(hFile: HANDLE, lpBuffer: [*]const u8, nNumberOfBytesToWrite: DWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) BOOL;205pub 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
211pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;207pub extern "kernel32" stdcallcc fn LoadLibraryW(lpLibFileName: [*]const u16) ?HMODULE;
212208
213pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;209pub extern "kernel32" stdcallcc fn GetProcAddress(hModule: HMODULE, lpProcName: [*]const u8) ?FARPROC;
lib/std/parker.zig+24-92
...@@ -76,107 +76,39 @@ const WindowsParker = struct {...@@ -76,107 +76,39 @@ const WindowsParker = struct {
76 pub fn deinit(self: *WindowsParker) void {}76 pub fn deinit(self: *WindowsParker) void {}
7777
78 pub fn unpark(self: *WindowsParker, ptr: *const u32) void {78 pub fn unpark(self: *WindowsParker, ptr: *const u32) void {
79 switch (Backend.get().*) {79 const handle = getEventHandlePtr().*;
80 .WaitAddress => |*backend| backend.unpark(ptr, &self.waiters),80 const key = @ptrCast(*const c_void, ptr);
81 .KeyedEvent => |*backend| backend.unpark(ptr, &self.waiters),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 };
82 }88 }
83 }89 }
8490
85 pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void {91 pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void {
86 switch (Backend.get().*) {92 const handle = getEventHandlePtr().*;
87 .WaitAddress => |*backend| backend.park(ptr, expected, &self.waiters),93 const key = @ptrCast(*const c_void, ptr);
88 .KeyedEvent => |*backend| backend.park(ptr, expected, &self.waiters),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);
89 }98 }
90 }99 }
91100
92 const Backend = union(enum) {101 var event_handle = std.lazyInit(windows.HANDLE);
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 }
137102
138 fn park(self: WaitAddress, ptr: *const u32, expected: u32, waiters: *u32) void {103 fn getEventHandlePtr() *const windows.HANDLE {
139 var compare = expected;104 return event_handle.get() orelse {
140 const addr = @ptrCast(*const c_void, ptr);105 const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE;
141 const cmp = @ptrCast(*const c_void, &compare);106 if (windows.ntdll.NtCreateKeyedEvent(&event_handle.data, access_mask, null, 0) != 0)
142 while (@atomicLoad(u32, ptr, .Acquire) == expected)107 @panic("Failed to setup an NT Keyed Event handle for the process");
143 _ = self.WaitOnAddress(addr, cmp, @sizeOf(u32), windows.INFINITE);108 event_handle.resolve();
144 }109 return &event_handle.data;
145 };110 };
146111 }
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 };
180};112};
181113
182const PosixParker = struct {114const PosixParker = struct {