authorgravatar for hi@viri.moeviri <hi@viri.moe> 2022-01-15 17:40:45-06:00
committergravatar for hi@viri.moeviri <hi@viri.moe> 2022-02-15 01:20:54-06:00
log0bde55e881a14e4a871c216610dd10b386640f2e
tree8679dc484052d1897cbb8858e87028333ef54ec9
parent12d6bcec029dbb11bd533d0d0f0cc723aa71bc9d
signaturelock-open Commit is signed but in an unrecognized format.

std.Thread(windows): use NT internals for name fns


3 files changed, 39 insertions(+), 41 deletions(-)

lib/std/Thread.zig+39-23
...@@ -4,6 +4,7 @@...@@ -4,6 +4,7 @@
44
5const std = @import("std.zig");5const std = @import("std.zig");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const math = std.math;
7const os = std.os;8const os = std.os;
8const assert = std.debug.assert;9const assert = std.debug.assert;
9const target = builtin.target;10const target = builtin.target;
...@@ -85,20 +86,28 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {...@@ -85,20 +86,28 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
85 try file.writer().writeAll(name);86 try file.writer().writeAll(name);
86 return;87 return;
87 },88 },
88 .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| {89 .windows => {
89 // SetThreadDescription is only available since version 1607, which is 10.0.14393.79590 var buf: [max_name_len]u16 = undefined;
90 // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK91 const len = try std.unicode.utf8ToUtf16Le(&buf, name);
91 if (!res) return error.Unsupported;92 const byte_len = math.cast(c_ushort, len * 2) catch return error.NameTooLong;
9293
93 var name_buf_w: [max_name_len:0]u16 = undefined;94 // Note: NT allocates its own copy, no use-after-free here.
94 const length = try std.unicode.utf8ToUtf16Le(&name_buf_w, name);95 const unicode_string = os.windows.UNICODE_STRING{
95 name_buf_w[length] = 0;96 .Length = byte_len,
97 .MaximumLength = byte_len,
98 .Buffer = &buf,
99 };
96100
97 try os.windows.SetThreadDescription(101 switch (os.windows.ntdll.NtSetInformationThread(
98 self.getHandle(),102 self.getHandle(),
99 @ptrCast(os.windows.LPWSTR, &name_buf_w),103 .ThreadNameInformation,
100 );104 &unicode_string,
101 return;105 @sizeOf(os.windows.UNICODE_STRING),
106 )) {
107 .SUCCESS => return,
108 .NOT_IMPLEMENTED => return error.Unsupported,
109 else => |err| return os.windows.unexpectedStatus(err),
110 }
102 },111 },
103 .macos, .ios, .watchos, .tvos => if (use_pthreads) {112 .macos, .ios, .watchos, .tvos => if (use_pthreads) {
104 // There doesn't seem to be a way to set the name for an arbitrary thread, only the current one.113 // There doesn't seem to be a way to set the name for an arbitrary thread, only the current one.
...@@ -188,18 +197,25 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co...@@ -188,18 +197,25 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
188 // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.197 // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.
189 return error.Unsupported;198 return error.Unsupported;
190 },199 },
191 .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| {200 .windows => {
192 // GetThreadDescription is only available since version 1607, which is 10.0.14393.795201 const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len);
193 // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK202 var buf: [buf_capacity]u8 align(@alignOf(os.windows.UNICODE_STRING)) = undefined;
194 if (!res) return error.Unsupported;
195
196 var name_w: os.windows.LPWSTR = undefined;
197 try os.windows.GetThreadDescription(self.getHandle(), &name_w);
198 defer os.windows.LocalFree(name_w);
199203
200 const data_len = try std.unicode.utf16leToUtf8(buffer, std.mem.sliceTo(name_w, 0));204 switch (os.windows.ntdll.NtQueryInformationThread(
201205 self.getHandle(),
202 return if (data_len >= 1) buffer[0..data_len] else null;206 .ThreadNameInformation,
207 &buf,
208 buf_capacity,
209 null,
210 )) {
211 .SUCCESS => {
212 const string = @ptrCast(*const os.windows.UNICODE_STRING, &buf);
213 const len = try std.unicode.utf16leToUtf8(buffer, string.Buffer[0 .. string.Length / 2]);
214 return if (len > 0) buffer[0..len] else null;
215 },
216 .NOT_IMPLEMENTED => return error.Unsupported,
217 else => |err| return os.windows.unexpectedStatus(err),
218 }
203 },219 },
204 .macos, .ios, .watchos, .tvos => if (use_pthreads) {220 .macos, .ios, .watchos, .tvos => if (use_pthreads) {
205 const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);221 const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
lib/std/os/windows.zig-15
...@@ -2029,21 +2029,6 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {...@@ -2029,21 +2029,6 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
2029 return error.Unexpected;2029 return error.Unexpected;
2030}2030}
20312031
2032pub fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) !void {
2033 if (kernel32.SetThreadDescription(hThread, lpThreadDescription) == 0) {
2034 switch (kernel32.GetLastError()) {
2035 else => |err| return unexpectedError(err),
2036 }
2037 }
2038}
2039pub fn GetThreadDescription(hThread: HANDLE, ppszThreadDescription: *LPWSTR) !void {
2040 if (kernel32.GetThreadDescription(hThread, ppszThreadDescription) == 0) {
2041 switch (kernel32.GetLastError()) {
2042 else => |err| return unexpectedError(err),
2043 }
2044 }
2045}
2046
2047pub const Win32Error = @import("windows/win32error.zig").Win32Error;2032pub const Win32Error = @import("windows/win32error.zig").Win32Error;
2048pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;2033pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;
2049pub const LANG = @import("windows/lang.zig");2034pub const LANG = @import("windows/lang.zig");
lib/std/os/windows/kernel32.zig-3
...@@ -400,6 +400,3 @@ pub extern "kernel32" fn SleepConditionVariableSRW(...@@ -400,6 +400,3 @@ pub extern "kernel32" fn SleepConditionVariableSRW(
400pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN;400pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN;
401pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;401pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;
402pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;402pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;
403
404pub extern "kernel32" fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) callconv(WINAPI) HRESULT;
405pub extern "kernel32" fn GetThreadDescription(hThread: HANDLE, ppszThreadDescription: *LPWSTR) callconv(WINAPI) HRESULT;