-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite MacOS implementation to use public APIs only (#6)
- Loading branch information
1 parent
9669e08
commit b12a1c8
Showing
2 changed files
with
39 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |