authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-15 13:23:09+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-15 13:23:09+02:00
logcf5009f9af118716cbe97a28957cb1ca8d047f44
tree7d41fe7f2ea3049114e43363aa3b15ace2a1e54e
parent078aa5f7b20e6e705378713a717bc2dd9afb8835
parent0bde55e881a14e4a871c216610dd10b386640f2e
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10003 from viriuwu/nt-thread-name

std.Thread.getName/setName: rework windows implementation

4 files changed, 126 insertions(+), 63 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;
...@@ -86,20 +87,28 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {...@@ -86,20 +87,28 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
86 try file.writer().writeAll(name);87 try file.writer().writeAll(name);
87 return;88 return;
88 },89 },
89 .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| {90 .windows => {
90 // SetThreadDescription is only available since version 1607, which is 10.0.14393.79591 var buf: [max_name_len]u16 = undefined;
91 // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK92 const len = try std.unicode.utf8ToUtf16Le(&buf, name);
92 if (!res) return error.Unsupported;93 const byte_len = math.cast(c_ushort, len * 2) catch return error.NameTooLong;
9394
94 var name_buf_w: [max_name_len:0]u16 = undefined;95 // Note: NT allocates its own copy, no use-after-free here.
95 const length = try std.unicode.utf8ToUtf16Le(&name_buf_w, name);96 const unicode_string = os.windows.UNICODE_STRING{
96 name_buf_w[length] = 0;97 .Length = byte_len,
98 .MaximumLength = byte_len,
99 .Buffer = &buf,
100 };
97101
98 try os.windows.SetThreadDescription(102 switch (os.windows.ntdll.NtSetInformationThread(
99 self.getHandle(),103 self.getHandle(),
100 @ptrCast(os.windows.LPWSTR, &name_buf_w),104 .ThreadNameInformation,
101 );105 &unicode_string,
102 return;106 @sizeOf(os.windows.UNICODE_STRING),
107 )) {
108 .SUCCESS => return,
109 .NOT_IMPLEMENTED => return error.Unsupported,
110 else => |err| return os.windows.unexpectedStatus(err),
111 }
103 },112 },
104 .macos, .ios, .watchos, .tvos => if (use_pthreads) {113 .macos, .ios, .watchos, .tvos => if (use_pthreads) {
105 // There doesn't seem to be a way to set the name for an arbitrary thread, only the current one.114 // There doesn't seem to be a way to set the name for an arbitrary thread, only the current one.
...@@ -189,18 +198,25 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co...@@ -189,18 +198,25 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
189 // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.198 // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.
190 return error.Unsupported;199 return error.Unsupported;
191 },200 },
192 .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| {201 .windows => {
193 // GetThreadDescription is only available since version 1607, which is 10.0.14393.795202 const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len);
194 // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK203 var buf: [buf_capacity]u8 align(@alignOf(os.windows.UNICODE_STRING)) = undefined;
195 if (!res) return error.Unsupported;
196
197 var name_w: os.windows.LPWSTR = undefined;
198 try os.windows.GetThreadDescription(self.getHandle(), &name_w);
199 defer os.windows.LocalFree(name_w);
200204
201 const data_len = try std.unicode.utf16leToUtf8(buffer, std.mem.sliceTo(name_w, 0));205 switch (os.windows.ntdll.NtQueryInformationThread(
202206 self.getHandle(),
203 return if (data_len >= 1) buffer[0..data_len] else null;207 .ThreadNameInformation,
208 &buf,
209 buf_capacity,
210 null,
211 )) {
212 .SUCCESS => {
213 const string = @ptrCast(*const os.windows.UNICODE_STRING, &buf);
214 const len = try std.unicode.utf16leToUtf8(buffer, string.Buffer[0 .. string.Length / 2]);
215 return if (len > 0) buffer[0..len] else null;
216 },
217 .NOT_IMPLEMENTED => return error.Unsupported,
218 else => |err| return os.windows.unexpectedStatus(err),
219 }
204 },220 },
205 .macos, .ios, .watchos, .tvos => if (use_pthreads) {221 .macos, .ios, .watchos, .tvos => if (use_pthreads) {
206 const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);222 const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
lib/std/os/windows.zig-15
...@@ -2042,21 +2042,6 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {...@@ -2042,21 +2042,6 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
2042 return error.Unexpected;2042 return error.Unexpected;
2043}2043}
20442044
2045pub fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) !void {
2046 if (kernel32.SetThreadDescription(hThread, lpThreadDescription) == 0) {
2047 switch (kernel32.GetLastError()) {
2048 else => |err| return unexpectedError(err),
2049 }
2050 }
2051}
2052pub fn GetThreadDescription(hThread: HANDLE, ppszThreadDescription: *LPWSTR) !void {
2053 if (kernel32.GetThreadDescription(hThread, ppszThreadDescription) == 0) {
2054 switch (kernel32.GetLastError()) {
2055 else => |err| return unexpectedError(err),
2056 }
2057 }
2058}
2059
2060pub const Win32Error = @import("windows/win32error.zig").Win32Error;2045pub const Win32Error = @import("windows/win32error.zig").Win32Error;
2061pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;2046pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;
2062pub const LANG = @import("windows/lang.zig");2047pub const LANG = @import("windows/lang.zig");
lib/std/os/windows/kernel32.zig-3
...@@ -402,6 +402,3 @@ pub extern "kernel32" fn SleepConditionVariableSRW(...@@ -402,6 +402,3 @@ pub extern "kernel32" fn SleepConditionVariableSRW(
402pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN;402pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN;
403pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;403pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;
404pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;404pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void;
405
406pub extern "kernel32" fn SetThreadDescription(hThread: HANDLE, lpThreadDescription: LPCWSTR) callconv(WINAPI) HRESULT;
407pub extern "kernel32" fn GetThreadDescription(hThread: HANDLE, ppszThreadDescription: *LPWSTR) callconv(WINAPI) HRESULT;
lib/std/os/windows/ntdll.zig+87-22
...@@ -23,23 +23,88 @@ const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION;...@@ -23,23 +23,88 @@ const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION;
23const SIZE_T = windows.SIZE_T;23const SIZE_T = windows.SIZE_T;
24const CURDIR = windows.CURDIR;24const CURDIR = windows.CURDIR;
2525
26pub extern "NtDll" fn RtlGetVersion(26pub const THREADINFOCLASS = enum(c_int) {
27 ThreadBasicInformation,
28 ThreadTimes,
29 ThreadPriority,
30 ThreadBasePriority,
31 ThreadAffinityMask,
32 ThreadImpersonationToken,
33 ThreadDescriptorTableEntry,
34 ThreadEnableAlignmentFaultFixup,
35 ThreadEventPair_Reusable,
36 ThreadQuerySetWin32StartAddress,
37 ThreadZeroTlsCell,
38 ThreadPerformanceCount,
39 ThreadAmILastThread,
40 ThreadIdealProcessor,
41 ThreadPriorityBoost,
42 ThreadSetTlsArrayAddress,
43 ThreadIsIoPending,
44 // Windows 2000+ from here
45 ThreadHideFromDebugger,
46 // Windows XP+ from here
47 ThreadBreakOnTermination,
48 ThreadSwitchLegacyState,
49 ThreadIsTerminated,
50 // Windows Vista+ from here
51 ThreadLastSystemCall,
52 ThreadIoPriority,
53 ThreadCycleTime,
54 ThreadPagePriority,
55 ThreadActualBasePriority,
56 ThreadTebInformation,
57 ThreadCSwitchMon,
58 // Windows 7+ from here
59 ThreadCSwitchPmu,
60 ThreadWow64Context,
61 ThreadGroupInformation,
62 ThreadUmsInformation,
63 ThreadCounterProfiling,
64 ThreadIdealProcessorEx,
65 // Windows 8+ from here
66 ThreadCpuAccountingInformation,
67 // Windows 8.1+ from here
68 ThreadSuspendCount,
69 // Windows 10+ from here
70 ThreadHeterogeneousCpuPolicy,
71 ThreadContainerId,
72 ThreadNameInformation,
73 ThreadSelectedCpuSets,
74 ThreadSystemThreadInformation,
75 ThreadActualGroupAffinity,
76};
77pub extern "ntdll" fn NtQueryInformationThread(
78 ThreadHandle: HANDLE,
79 ThreadInformationClass: THREADINFOCLASS,
80 ThreadInformation: *anyopaque,
81 ThreadInformationLength: ULONG,
82 ReturnLength: ?*ULONG,
83) callconv(WINAPI) NTSTATUS;
84pub extern "ntdll" fn NtSetInformationThread(
85 ThreadHandle: HANDLE,
86 ThreadInformationClass: THREADINFOCLASS,
87 ThreadInformation: *const anyopaque,
88 ThreadInformationLength: ULONG,
89) callconv(WINAPI) NTSTATUS;
90
91pub extern "ntdll" fn RtlGetVersion(
27 lpVersionInformation: *RTL_OSVERSIONINFOW,92 lpVersionInformation: *RTL_OSVERSIONINFOW,
28) callconv(WINAPI) NTSTATUS;93) callconv(WINAPI) NTSTATUS;
29pub extern "NtDll" fn RtlCaptureStackBackTrace(94pub extern "ntdll" fn RtlCaptureStackBackTrace(
30 FramesToSkip: DWORD,95 FramesToSkip: DWORD,
31 FramesToCapture: DWORD,96 FramesToCapture: DWORD,
32 BackTrace: **anyopaque,97 BackTrace: **anyopaque,
33 BackTraceHash: ?*DWORD,98 BackTraceHash: ?*DWORD,
34) callconv(WINAPI) WORD;99) callconv(WINAPI) WORD;
35pub extern "NtDll" fn NtQueryInformationFile(100pub extern "ntdll" fn NtQueryInformationFile(
36 FileHandle: HANDLE,101 FileHandle: HANDLE,
37 IoStatusBlock: *IO_STATUS_BLOCK,102 IoStatusBlock: *IO_STATUS_BLOCK,
38 FileInformation: *anyopaque,103 FileInformation: *anyopaque,
39 Length: ULONG,104 Length: ULONG,
40 FileInformationClass: FILE_INFORMATION_CLASS,105 FileInformationClass: FILE_INFORMATION_CLASS,
41) callconv(WINAPI) NTSTATUS;106) callconv(WINAPI) NTSTATUS;
42pub extern "NtDll" fn NtSetInformationFile(107pub extern "ntdll" fn NtSetInformationFile(
43 FileHandle: HANDLE,108 FileHandle: HANDLE,
44 IoStatusBlock: *IO_STATUS_BLOCK,109 IoStatusBlock: *IO_STATUS_BLOCK,
45 FileInformation: PVOID,110 FileInformation: PVOID,
...@@ -47,12 +112,12 @@ pub extern "NtDll" fn NtSetInformationFile(...@@ -47,12 +112,12 @@ pub extern "NtDll" fn NtSetInformationFile(
47 FileInformationClass: FILE_INFORMATION_CLASS,112 FileInformationClass: FILE_INFORMATION_CLASS,
48) callconv(WINAPI) NTSTATUS;113) callconv(WINAPI) NTSTATUS;
49114
50pub extern "NtDll" fn NtQueryAttributesFile(115pub extern "ntdll" fn NtQueryAttributesFile(
51 ObjectAttributes: *OBJECT_ATTRIBUTES,116 ObjectAttributes: *OBJECT_ATTRIBUTES,
52 FileAttributes: *FILE_BASIC_INFORMATION,117 FileAttributes: *FILE_BASIC_INFORMATION,
53) callconv(WINAPI) NTSTATUS;118) callconv(WINAPI) NTSTATUS;
54119
55pub extern "NtDll" fn NtCreateFile(120pub extern "ntdll" fn NtCreateFile(
56 FileHandle: *HANDLE,121 FileHandle: *HANDLE,
57 DesiredAccess: ACCESS_MASK,122 DesiredAccess: ACCESS_MASK,
58 ObjectAttributes: *OBJECT_ATTRIBUTES,123 ObjectAttributes: *OBJECT_ATTRIBUTES,
...@@ -65,7 +130,7 @@ pub extern "NtDll" fn NtCreateFile(...@@ -65,7 +130,7 @@ pub extern "NtDll" fn NtCreateFile(
65 EaBuffer: ?*anyopaque,130 EaBuffer: ?*anyopaque,
66 EaLength: ULONG,131 EaLength: ULONG,
67) callconv(WINAPI) NTSTATUS;132) callconv(WINAPI) NTSTATUS;
68pub extern "NtDll" fn NtDeviceIoControlFile(133pub extern "ntdll" fn NtDeviceIoControlFile(
69 FileHandle: HANDLE,134 FileHandle: HANDLE,
70 Event: ?HANDLE,135 Event: ?HANDLE,
71 ApcRoutine: ?IO_APC_ROUTINE,136 ApcRoutine: ?IO_APC_ROUTINE,
...@@ -77,7 +142,7 @@ pub extern "NtDll" fn NtDeviceIoControlFile(...@@ -77,7 +142,7 @@ pub extern "NtDll" fn NtDeviceIoControlFile(
77 OutputBuffer: ?PVOID,142 OutputBuffer: ?PVOID,
78 OutputBufferLength: ULONG,143 OutputBufferLength: ULONG,
79) callconv(WINAPI) NTSTATUS;144) callconv(WINAPI) NTSTATUS;
80pub extern "NtDll" fn NtFsControlFile(145pub extern "ntdll" fn NtFsControlFile(
81 FileHandle: HANDLE,146 FileHandle: HANDLE,
82 Event: ?HANDLE,147 Event: ?HANDLE,
83 ApcRoutine: ?IO_APC_ROUTINE,148 ApcRoutine: ?IO_APC_ROUTINE,
...@@ -89,16 +154,16 @@ pub extern "NtDll" fn NtFsControlFile(...@@ -89,16 +154,16 @@ pub extern "NtDll" fn NtFsControlFile(
89 OutputBuffer: ?PVOID,154 OutputBuffer: ?PVOID,
90 OutputBufferLength: ULONG,155 OutputBufferLength: ULONG,
91) callconv(WINAPI) NTSTATUS;156) callconv(WINAPI) NTSTATUS;
92pub extern "NtDll" fn NtClose(Handle: HANDLE) callconv(WINAPI) NTSTATUS;157pub extern "ntdll" fn NtClose(Handle: HANDLE) callconv(WINAPI) NTSTATUS;
93pub extern "NtDll" fn RtlDosPathNameToNtPathName_U(158pub extern "ntdll" fn RtlDosPathNameToNtPathName_U(
94 DosPathName: [*:0]const u16,159 DosPathName: [*:0]const u16,
95 NtPathName: *UNICODE_STRING,160 NtPathName: *UNICODE_STRING,
96 NtFileNamePart: ?*?[*:0]const u16,161 NtFileNamePart: ?*?[*:0]const u16,
97 DirectoryInfo: ?*CURDIR,162 DirectoryInfo: ?*CURDIR,
98) callconv(WINAPI) BOOL;163) callconv(WINAPI) BOOL;
99pub extern "NtDll" fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) callconv(WINAPI) void;164pub extern "ntdll" fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) callconv(WINAPI) void;
100165
101pub extern "NtDll" fn NtQueryDirectoryFile(166pub extern "ntdll" fn NtQueryDirectoryFile(
102 FileHandle: HANDLE,167 FileHandle: HANDLE,
103 Event: ?HANDLE,168 Event: ?HANDLE,
104 ApcRoutine: ?IO_APC_ROUTINE,169 ApcRoutine: ?IO_APC_ROUTINE,
...@@ -112,30 +177,30 @@ pub extern "NtDll" fn NtQueryDirectoryFile(...@@ -112,30 +177,30 @@ pub extern "NtDll" fn NtQueryDirectoryFile(
112 RestartScan: BOOLEAN,177 RestartScan: BOOLEAN,
113) callconv(WINAPI) NTSTATUS;178) callconv(WINAPI) NTSTATUS;
114179
115pub extern "NtDll" fn NtCreateKeyedEvent(180pub extern "ntdll" fn NtCreateKeyedEvent(
116 KeyedEventHandle: *HANDLE,181 KeyedEventHandle: *HANDLE,
117 DesiredAccess: ACCESS_MASK,182 DesiredAccess: ACCESS_MASK,
118 ObjectAttributes: ?PVOID,183 ObjectAttributes: ?PVOID,
119 Flags: ULONG,184 Flags: ULONG,
120) callconv(WINAPI) NTSTATUS;185) callconv(WINAPI) NTSTATUS;
121186
122pub extern "NtDll" fn NtReleaseKeyedEvent(187pub extern "ntdll" fn NtReleaseKeyedEvent(
123 EventHandle: ?HANDLE,188 EventHandle: ?HANDLE,
124 Key: ?*const anyopaque,189 Key: ?*const anyopaque,
125 Alertable: BOOLEAN,190 Alertable: BOOLEAN,
126 Timeout: ?*const LARGE_INTEGER,191 Timeout: ?*const LARGE_INTEGER,
127) callconv(WINAPI) NTSTATUS;192) callconv(WINAPI) NTSTATUS;
128193
129pub extern "NtDll" fn NtWaitForKeyedEvent(194pub extern "ntdll" fn NtWaitForKeyedEvent(
130 EventHandle: ?HANDLE,195 EventHandle: ?HANDLE,
131 Key: ?*const anyopaque,196 Key: ?*const anyopaque,
132 Alertable: BOOLEAN,197 Alertable: BOOLEAN,
133 Timeout: ?*const LARGE_INTEGER,198 Timeout: ?*const LARGE_INTEGER,
134) callconv(WINAPI) NTSTATUS;199) callconv(WINAPI) NTSTATUS;
135200
136pub extern "NtDll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(WINAPI) NTSTATUS;201pub extern "ntdll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(WINAPI) NTSTATUS;
137202
138pub extern "NtDll" fn NtQueryObject(203pub extern "ntdll" fn NtQueryObject(
139 Handle: HANDLE,204 Handle: HANDLE,
140 ObjectInformationClass: OBJECT_INFORMATION_CLASS,205 ObjectInformationClass: OBJECT_INFORMATION_CLASS,
141 ObjectInformation: PVOID,206 ObjectInformation: PVOID,
...@@ -143,22 +208,22 @@ pub extern "NtDll" fn NtQueryObject(...@@ -143,22 +208,22 @@ pub extern "NtDll" fn NtQueryObject(
143 ReturnLength: ?*ULONG,208 ReturnLength: ?*ULONG,
144) callconv(WINAPI) NTSTATUS;209) callconv(WINAPI) NTSTATUS;
145210
146pub extern "NtDll" fn RtlWakeAddressAll(211pub extern "ntdll" fn RtlWakeAddressAll(
147 Address: ?*const anyopaque,212 Address: ?*const anyopaque,
148) callconv(WINAPI) void;213) callconv(WINAPI) void;
149214
150pub extern "NtDll" fn RtlWakeAddressSingle(215pub extern "ntdll" fn RtlWakeAddressSingle(
151 Address: ?*const anyopaque,216 Address: ?*const anyopaque,
152) callconv(WINAPI) void;217) callconv(WINAPI) void;
153218
154pub extern "NtDll" fn RtlWaitOnAddress(219pub extern "ntdll" fn RtlWaitOnAddress(
155 Address: ?*const anyopaque,220 Address: ?*const anyopaque,
156 CompareAddress: ?*const anyopaque,221 CompareAddress: ?*const anyopaque,
157 AddressSize: SIZE_T,222 AddressSize: SIZE_T,
158 Timeout: ?*const LARGE_INTEGER,223 Timeout: ?*const LARGE_INTEGER,
159) callconv(WINAPI) NTSTATUS;224) callconv(WINAPI) NTSTATUS;
160225
161pub extern "NtDll" fn NtLockFile(226pub extern "ntdll" fn NtLockFile(
162 FileHandle: HANDLE,227 FileHandle: HANDLE,
163 Event: ?HANDLE,228 Event: ?HANDLE,
164 ApcRoutine: ?*IO_APC_ROUTINE,229 ApcRoutine: ?*IO_APC_ROUTINE,
...@@ -171,7 +236,7 @@ pub extern "NtDll" fn NtLockFile(...@@ -171,7 +236,7 @@ pub extern "NtDll" fn NtLockFile(
171 ExclusiveLock: BOOLEAN,236 ExclusiveLock: BOOLEAN,
172) callconv(WINAPI) NTSTATUS;237) callconv(WINAPI) NTSTATUS;
173238
174pub extern "NtDll" fn NtUnlockFile(239pub extern "ntdll" fn NtUnlockFile(
175 FileHandle: HANDLE,240 FileHandle: HANDLE,
176 IoStatusBlock: *IO_STATUS_BLOCK,241 IoStatusBlock: *IO_STATUS_BLOCK,
177 ByteOffset: *const LARGE_INTEGER,242 ByteOffset: *const LARGE_INTEGER,