| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | | 4 | |
| 5 | const std = @import("std.zig"); | 5 | const std = @import("std.zig"); |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| | 7 | const math = std.math; |
| 7 | const os = std.os; | 8 | const os = std.os; |
| 8 | const assert = std.debug.assert; | 9 | const assert = std.debug.assert; |
| 9 | const target = builtin.target; | 10 | const 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.795 | 90 | var buf: [max_name_len]u16 = undefined; |
| 90 | // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK | 91 | 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; |
| 92 | | 93 | |
| 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 | }; |
| 96 | | 100 | |
| 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.795 | 201 | const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); |
| 193 | // See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK | 202 | 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); | | |
| 199 | | 203 | |
| 200 | const data_len = try std.unicode.utf16leToUtf8(buffer, std.mem.sliceTo(name_w, 0)); | 204 | switch (os.windows.ntdll.NtQueryInformationThread( |
| 201 | | 205 | 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); |