Skip to content

Commit

Permalink
Rewrite MacOS implementation to use public APIs only (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
complexspaces authored Mar 11, 2022
1 parent 9669e08 commit b12a1c8
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Unreleased

- Modified MacOS implementation to be friendly towards Apple app store review guidelines.

# 0.1.2

- Add support for MacOS
Expand Down
51 changes: 35 additions & 16 deletions src/macos.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
extern crate libc;

use std::mem;
use std::num::NonZeroUsize;

const PROC_TASKINFO_SIZE: usize = mem::size_of::<libc::proc_taskinfo>();
use self::libc::{kern_return_t, mach_msg_type_number_t, mach_port_t, thread_t};

// This constant is from
// /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/
// usr/include/mach/machine/thread_state.h.
//
// It has not been updated since Apple devices started to support 64-bit ARM (iOS), so it
// should be very stable.
const THREAD_STATE_MAX: i32 = 1296;
#[allow(non_camel_case_types)]
// https://github.com/apple/darwin-xnu/blob/a1babec6b135d1f35b2590a1990af3c5c5393479/osfmk/mach/mach_types.defs#L155
type task_inspect_t = mach_port_t;
#[allow(non_camel_case_types)]
// https://github.com/apple/darwin-xnu/blob/a1babec6b135d1f35b2590a1990af3c5c5393479/osfmk/mach/mach_types.defs#L238
type thread_array_t = [thread_t; THREAD_STATE_MAX as usize];

extern "C" {
// https://developer.apple.com/documentation/kernel/1537751-task_threads/
fn task_threads(
target_task: task_inspect_t,
act_list: *mut thread_array_t,
act_listCnt: *mut mach_msg_type_number_t,
) -> kern_return_t;
}

pub(crate) fn num_threads() -> Option<NonZeroUsize> {
let mut pti: libc::proc_taskinfo = unsafe { mem::zeroed() };
// http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_threads.html
let mut thread_state = [0u32; THREAD_STATE_MAX as usize];
let mut thread_count = 0;

let result = unsafe {
libc::proc_pidinfo(
libc::getpid(),
libc::PROC_PIDTASKINFO,
0,
&mut pti as *mut libc::proc_taskinfo as *mut libc::c_void,
PROC_TASKINFO_SIZE as libc::c_int,
)
};
// Safety: `mach_task_self` always returns a valid value, `thread_state` is large enough, and
// both it and `thread_count` are writable.
let result =
unsafe { task_threads(libc::mach_task_self(), &mut thread_state, &mut thread_count) };

if result == PROC_TASKINFO_SIZE as libc::c_int {
return NonZeroUsize::new(pti.pti_threadnum as usize);
if result == libc::KERN_SUCCESS {
NonZeroUsize::new(thread_count as usize)
} else {
None
}

None
}

0 comments on commit b12a1c8

Please sign in to comment.