specter/memory/platform/
thread.rs1use std::ptr;
4
5use mach2::{
6 kern_return::KERN_SUCCESS,
7 mach_init::mach_thread_self,
8 mach_types::{thread_act_array_t, thread_act_t},
9 message::mach_msg_type_number_t,
10 port::mach_port_t,
11 task::task_threads,
12 thread_act::{thread_resume, thread_suspend},
13 traps::mach_task_self,
14 vm::mach_vm_deallocate,
15 vm_types::mach_vm_size_t,
16};
17
18use thiserror::Error;
19
20#[derive(Error, Debug)]
21pub enum ThreadError {
23 #[error("Failed to get task threads (kern_return: {0})")]
25 TaskThreadsFailed(i32),
26}
27
28pub unsafe fn suspend_other_threads() -> Result<Vec<mach_port_t>, ThreadError> {
36 unsafe {
37 let mut thread_list: thread_act_array_t = ptr::null_mut();
38 let mut thread_count: mach_msg_type_number_t = 0;
39
40 let kret = task_threads(mach_task_self(), &mut thread_list, &mut thread_count);
41 if kret != KERN_SUCCESS {
42 return Err(ThreadError::TaskThreadsFailed(kret));
43 }
44
45 let this_thread = mach_thread_self();
46 let mut suspended_threads = Vec::with_capacity(thread_count as usize);
47
48 let threads = std::slice::from_raw_parts(thread_list, thread_count as usize);
49
50 for &thread in threads {
51 if thread != this_thread && thread_suspend(thread) == KERN_SUCCESS {
52 suspended_threads.push(thread);
53 }
54 }
55
56 mach_vm_deallocate(
57 mach_task_self(),
58 thread_list as u64,
59 (thread_count as mach_vm_size_t)
60 * (std::mem::size_of::<thread_act_t>() as mach_vm_size_t),
61 );
62
63 Ok(suspended_threads)
64 }
65}
66
67pub unsafe fn resume_threads(threads: &[mach_port_t]) {
72 unsafe {
73 for &thread in threads {
74 thread_resume(thread);
75 }
76 }
77}