Commit f505cb96f4

Jakub Konka <kubkon@jakubkonka.com>
2022-12-13 12:53:10
darwin: add thread_act_t wrapper and helpers
1 parent 2efd0eb
Changed files (2)
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
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))) {