On Windows, the result is encoded as WTF-8. On other platforms, the result is an opaque sequence of bytes with no particular encoding.
pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]const u8
pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]const u8 {
buffer_ptr[max_name_len] = 0;
var buffer: [:0]u8 = buffer_ptr;
switch (native_os) {
.linux => if (use_pthreads) {
if (self.getHandle() == std.c.pthread_self()) {
// Get the name of the calling thread (no thread id required).
assert(try posix.prctl(.GET_NAME, .{@intFromPtr(buffer.ptr)}) == 0);
return std.mem.sliceTo(buffer, 0);
} else {
const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
switch (@as(posix.E, @fromBackingInt(@intCast(err)))) {
.SUCCESS => return std.mem.sliceTo(buffer, 0),
.RANGE => unreachable,
else => |e| return posix.unexpectedErrno(e),
}
}
} else {
var buf: [32]u8 = undefined;
const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});
const io = std.Options.debug_io;
const file = try Io.Dir.cwd().openFile(io, path, .{});
defer file.close(io);
var file_reader = file.readerStreaming(io, &.{});
const data_len = file_reader.interface.readSliceShort(buffer_ptr[0 .. max_name_len + 1]) catch |err| switch (err) {
error.ReadFailed => return file_reader.err.?,
};
return if (data_len >= 1) buffer[0 .. data_len - 1] else null;
},
.windows => {
const buf_capacity = @sizeOf(windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len);
var buf: [buf_capacity]u8 align(@alignOf(windows.UNICODE_STRING)) = undefined;
switch (windows.ntdll.NtQueryInformationThread(
self.getHandle(),
.NameInformation,
&buf,
buf_capacity,
null,
)) {
.SUCCESS => {
const string: *const windows.UNICODE_STRING = @ptrCast(&buf);
const len = std.unicode.wtf16LeToWtf8(buffer, string.slice());
return if (len > 0) buffer[0..len] else null;
},
.NOT_IMPLEMENTED => return error.Unsupported,
else => |err| return windows.unexpectedStatus(err),
}
},
.driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => if (use_pthreads) {
const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
switch (@as(posix.E, @fromBackingInt(@intCast(err)))) {
.SUCCESS => return std.mem.sliceTo(buffer, 0),
.SRCH => unreachable,
else => |e| return posix.unexpectedErrno(e),
}
},
.serenity => if (use_pthreads) {
const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
switch (@as(posix.E, @fromBackingInt(@intCast(err)))) {
.SUCCESS => return,
.NAMETOOLONG => unreachable,
.SRCH => unreachable,
.FAULT => unreachable,
else => |e| return posix.unexpectedErrno(e),
}
},
.netbsd, .illumos => if (use_pthreads) {
const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
switch (@as(posix.E, @fromBackingInt(@intCast(err)))) {
.SUCCESS => return std.mem.sliceTo(buffer, 0),
.INVAL => unreachable,
.SRCH => unreachable,
else => |e| return posix.unexpectedErrno(e),
}
},
.freebsd, .openbsd => if (use_pthreads) {
// Use pthread_get_name_np for FreeBSD because pthread_getname_np is FreeBSD 12.2+ only.
// TODO maybe revisit this if depending on FreeBSD 12.2+ is acceptable because pthread_getname_np can return an error.
std.c.pthread_get_name_np(self.getHandle(), buffer.ptr, max_name_len + 1);
return std.mem.sliceTo(buffer, 0);
},
.dragonfly => if (use_pthreads) {
const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
switch (@as(posix.E, @fromBackingInt(@intCast(err)))) {
.SUCCESS => return std.mem.sliceTo(buffer, 0),
.INVAL => unreachable,
.FAULT => unreachable,
.SRCH => unreachable,
else => |e| return posix.unexpectedErrno(e),
}
},
else => {},
}
return error.Unsupported;
}