|
4 | 4 |
|
5 | 5 | const std = @import("std.zig");
|
6 | 6 | const builtin = @import("builtin");
|
| 7 | +const math = std.math; |
7 | 8 | const os = std.os;
|
8 | 9 | const assert = std.debug.assert;
|
9 | 10 | const target = builtin.target;
|
@@ -85,20 +86,28 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
|
85 | 86 | try file.writer().writeAll(name);
|
86 | 87 | return;
|
87 | 88 | },
|
88 |
| - .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| { |
89 |
| - // SetThreadDescription is only available since version 1607, which is 10.0.14393.795 |
90 |
| - // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK |
91 |
| - if (!res) return error.Unsupported; |
92 |
| - |
93 |
| - var name_buf_w: [max_name_len:0]u16 = undefined; |
94 |
| - const length = try std.unicode.utf8ToUtf16Le(&name_buf_w, name); |
95 |
| - name_buf_w[length] = 0; |
| 89 | + .windows => { |
| 90 | + var buf: [max_name_len]u16 = undefined; |
| 91 | + const len = try std.unicode.utf8ToUtf16Le(&buf, name); |
| 92 | + const byte_len = math.cast(c_ushort, len * 2) catch return error.NameTooLong; |
| 93 | + |
| 94 | + // Note: NT allocates its own copy, no use-after-free here. |
| 95 | + const unicode_string = os.windows.UNICODE_STRING{ |
| 96 | + .Length = byte_len, |
| 97 | + .MaximumLength = byte_len, |
| 98 | + .Buffer = &buf, |
| 99 | + }; |
96 | 100 |
|
97 |
| - try os.windows.SetThreadDescription( |
| 101 | + switch (os.windows.ntdll.NtSetInformationThread( |
98 | 102 | self.getHandle(),
|
99 |
| - @ptrCast(os.windows.LPWSTR, &name_buf_w), |
100 |
| - ); |
101 |
| - return; |
| 103 | + .ThreadNameInformation, |
| 104 | + &unicode_string, |
| 105 | + @sizeOf(os.windows.UNICODE_STRING), |
| 106 | + )) { |
| 107 | + .SUCCESS => {}, |
| 108 | + .NOT_IMPLEMENTED => return error.Unsupported, |
| 109 | + else => |err| return os.windows.unexpectedStatus(err), |
| 110 | + } |
102 | 111 | },
|
103 | 112 | .macos, .ios, .watchos, .tvos => if (use_pthreads) {
|
104 | 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 | 197 | // musl doesn't provide pthread_getname_np and there's no way to retrieve the thread id of an arbitrary thread.
|
189 | 198 | return error.Unsupported;
|
190 | 199 | },
|
191 |
| - .windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| { |
192 |
| - // GetThreadDescription is only available since version 1607, which is 10.0.14393.795 |
193 |
| - // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK |
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); |
| 200 | + .windows => { |
| 201 | + const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); |
| 202 | + var buf: [buf_capacity]u8 align(@alignOf(os.windows.UNICODE_STRING)) = undefined; |
199 | 203 |
|
200 |
| - const data_len = try std.unicode.utf16leToUtf8(buffer, std.mem.sliceTo(name_w, 0)); |
201 |
| - |
202 |
| - return if (data_len >= 1) buffer[0..data_len] else null; |
| 204 | + switch (os.windows.ntdll.NtQueryInformationThread( |
| 205 | + self.getHandle(), |
| 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 | 220 | .macos, .ios, .watchos, .tvos => if (use_pthreads) {
|
205 | 221 | const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
|
|
0 commit comments