diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index e10dd5489f..3f768b5d4c 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -603,6 +603,9 @@ pub extern "c" fn thread_resume(thread: thread_act_t) kern_return_t; pub const THREAD_BASIC_INFO = 3; pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_basic_info) / @sizeOf(natural_t); +pub const THREAD_IDENTIFIER_INFO = 4; +pub const THREAD_IDENTIFIER_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_identifier_info) / @sizeOf(natural_t); + pub const thread_flavor_t = natural_t; pub const thread_info_t = *integer_t; pub const time_value_t = time_value; @@ -634,6 +637,17 @@ pub const thread_basic_info = extern struct { sleep_time: integer_t, }; +pub const thread_identifier_info = extern struct { + /// System-wide unique 64-bit thread id + thread_id: u64, + + /// Handle to be used by libproc + thread_handle: u64, + + /// libdispatch queue address + dispatch_qaddr: u64, +}; + /// Cachability pub const MATTR_CACHE = 1; /// Migrability diff --git a/lib/std/os/darwin.zig b/lib/std/os/darwin.zig index 0cf35a6306..48d4c28b7c 100644 --- a/lib/std/os/darwin.zig +++ b/lib/std/os/darwin.zig @@ -17,11 +17,11 @@ const mach_task = if (builtin.target.isDarwin()) struct { Unexpected, }; - pub const MachTask = struct { + pub const MachTask = extern struct { port: std.c.mach_port_name_t, pub fn isValid(self: MachTask) bool { - return self.port != 0; + return self.port != std.c.TASK_NULL; } pub fn allocatePort(self: MachTask, right: std.c.MACH_PORT_RIGHT) MachError!MachTask { @@ -439,11 +439,11 @@ const mach_task = if (builtin.target.isDarwin()) struct { } } - pub fn getThreads(task: MachTask) MachError![]std.c.mach_port_t { + pub fn getThreads(task: MachTask) MachError![]ThreadId { var thread_list: std.c.mach_port_array_t = undefined; var thread_count: std.c.mach_msg_type_number_t = undefined; switch (std.c.getKernError(std.c.task_threads(task.port, &thread_list, &thread_count))) { - .SUCCESS => return thread_list[0..thread_count], + .SUCCESS => return @ptrCast([*]ThreadId, thread_list)[0..thread_count], else => |err| { log.err("task_threads kernel call failed with error code: {s}", .{@tagName(err)}); return error.Unexpected; @@ -452,6 +452,44 @@ const mach_task = if (builtin.target.isDarwin()) struct { } }; + pub const ThreadId = extern struct { + id: std.c.thread_act_t, + + pub fn getBasicInfo(thread_id: ThreadId) MachError!std.c.thread_basic_info { + var info: std.c.thread_basic_info = undefined; + var count = std.c.THREAD_BASIC_INFO_COUNT; + switch (std.c.getKernError(std.c.thread_info( + thread_id.id, + std.c.THREAD_BASIC_INFO, + @ptrCast(std.c.thread_info_t, &info), + &count, + ))) { + .SUCCESS => return info, + else => |err| { + log.err("thread_info kernel call failed with error code: {s}", .{@tagName(err)}); + return error.Unexpected; + }, + } + } + + pub fn getIdentifierInfo(thread_id: ThreadId) MachError!std.c.thread_identifier_info { + var info: std.c.thread_identifier_info = undefined; + var count = std.c.THREAD_IDENTIFIER_INFO_COUNT; + switch (std.c.getKernError(std.c.thread_info( + thread_id.id, + std.c.THREAD_IDENTIFIER_INFO, + @ptrCast(std.c.thread_info_t, &info), + &count, + ))) { + .SUCCESS => return info, + else => |err| { + log.err("thread_info kernel call failed with error code: {s}", .{@tagName(err)}); + return error.Unexpected; + }, + } + } + }; + pub fn machTaskForPid(pid: std.os.pid_t) MachError!MachTask { var port: std.c.mach_port_name_t = undefined; switch (std.c.getKernError(std.c.task_for_pid(std.c.mach_task_self(), pid, &port))) {