1use crate::{Error, Result};
4
5pub fn pin_to_core(core_id: usize) -> Result<()> {
9 #[cfg(target_os = "linux")]
10 {
11 let cpu_set_words = usize::try_from(libc::CPU_SETSIZE)
12 .unwrap_or(1024)
13 .div_ceil(usize::BITS as usize);
14 let max_core = cpu_set_words * usize::BITS as usize;
15 if core_id >= max_core {
16 return Err(Error::System {
17 operation: "sched_setaffinity",
18 source: std::io::Error::from(std::io::ErrorKind::InvalidInput),
19 });
20 }
21
22 let mut mask = vec![0usize; cpu_set_words];
23 mask[core_id / usize::BITS as usize] |= 1usize << (core_id % usize::BITS as usize);
24
25 let result = unsafe {
27 libc::sched_setaffinity(
28 0,
29 std::mem::size_of_val(mask.as_slice()),
30 mask.as_ptr().cast::<libc::cpu_set_t>(),
31 )
32 };
33 if result != 0 {
34 return Err(Error::System {
35 operation: "sched_setaffinity",
36 source: std::io::Error::last_os_error(),
37 });
38 }
39 }
40
41 #[cfg(not(target_os = "linux"))]
42 {
43 let _ = core_id;
44 }
45
46 Ok(())
47}
48
49pub fn read_irq_affinity(irq: u32) -> Result<Vec<u32>> {
59 #[cfg(target_os = "linux")]
60 {
61 let path = format!("/proc/irq/{irq}/smp_affinity");
62 let content = std::fs::read_to_string(&path).map_err(|source| Error::System {
63 operation: "read_irq_affinity",
64 source,
65 })?;
66 let mut cores = Vec::new();
68 for (group_idx, chunk) in content.trim().split(',').rev().enumerate() {
69 let mask = u64::from_str_radix(chunk.trim(), 16).map_err(|_| Error::System {
70 operation: "read_irq_affinity",
71 source: std::io::Error::new(
72 std::io::ErrorKind::InvalidData,
73 format!("malformed affinity mask chunk: {chunk}"),
74 ),
75 })?;
76 for bit in 0..64 {
77 if mask & (1 << bit) != 0 {
78 let core = u32::try_from(group_idx * 64 + bit).map_err(|_| Error::System {
79 operation: "read_irq_affinity",
80 source: std::io::Error::new(
81 std::io::ErrorKind::InvalidData,
82 "affinity mask core index overflow",
83 ),
84 })?;
85 cores.push(core);
86 }
87 }
88 }
89 Ok(cores)
90 }
91 #[cfg(not(target_os = "linux"))]
92 {
93 let _ = irq;
94 Ok(Vec::new())
95 }
96}
97
98pub fn pin_to_numa_node(node: u32) -> Result<()> {
102 #[cfg(target_os = "linux")]
103 {
104 crate::numa::pin_to_node(node)
105 }
106
107 #[cfg(not(target_os = "linux"))]
108 {
109 let _ = node;
110 Ok(())
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::{pin_to_core, pin_to_numa_node};
117
118 #[test]
119 fn affinity_helpers_are_non_fatal() {
120 let _ = pin_to_core(0);
121 let _ = pin_to_numa_node(0);
122 }
123}