xref: /aosp_15_r20/external/crosvm/base/src/sys/windows/sched.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
6*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::processthreadsapi::GetCurrentThread;
7*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::SetThreadAffinityMask;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use super::errno_result;
10*bb4ee6a4SAndroid Build Coastguard Worker use super::Error;
11*bb4ee6a4SAndroid Build Coastguard Worker use super::Result;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker /// Set the CPU affinity of the current thread to a given set of CPUs.
14*bb4ee6a4SAndroid Build Coastguard Worker /// The cpus must be a subset of those in the process affinity mask.
15*bb4ee6a4SAndroid Build Coastguard Worker /// If there are more than 64 processors, the affinity mask must specify
16*bb4ee6a4SAndroid Build Coastguard Worker /// processors in the thread's current processor group.
17*bb4ee6a4SAndroid Build Coastguard Worker ///
18*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the previous bits set for cpu_affinity.
19*bb4ee6a4SAndroid Build Coastguard Worker /// # Examples
20*bb4ee6a4SAndroid Build Coastguard Worker ///
21*bb4ee6a4SAndroid Build Coastguard Worker /// Set the calling thread's CPU affinity so it will run on only CPUs
22*bb4ee6a4SAndroid Build Coastguard Worker /// 0, 1, 5, and 6.
23*bb4ee6a4SAndroid Build Coastguard Worker ///
24*bb4ee6a4SAndroid Build Coastguard Worker /// ```
25*bb4ee6a4SAndroid Build Coastguard Worker /// # use base::windows::set_cpu_affinity;
26*bb4ee6a4SAndroid Build Coastguard Worker ///   set_cpu_affinity(vec![0, 1, 5, 6]).unwrap();
27*bb4ee6a4SAndroid Build Coastguard Worker /// ```
set_cpu_affinity<I: IntoIterator<Item = usize>>(cpus: I) -> Result<usize>28*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_cpu_affinity<I: IntoIterator<Item = usize>>(cpus: I) -> Result<usize> {
29*bb4ee6a4SAndroid Build Coastguard Worker     let mut affinity_mask: usize = 0;
30*bb4ee6a4SAndroid Build Coastguard Worker     for cpu in cpus {
31*bb4ee6a4SAndroid Build Coastguard Worker         if cpu >= 64 {
32*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::new(EINVAL));
33*bb4ee6a4SAndroid Build Coastguard Worker         }
34*bb4ee6a4SAndroid Build Coastguard Worker         affinity_mask |= 1 << cpu;
35*bb4ee6a4SAndroid Build Coastguard Worker     }
36*bb4ee6a4SAndroid Build Coastguard Worker     set_cpu_affinity_mask(affinity_mask)
37*bb4ee6a4SAndroid Build Coastguard Worker }
38*bb4ee6a4SAndroid Build Coastguard Worker 
set_cpu_affinity_mask(affinity_mask: usize) -> Result<usize>39*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_cpu_affinity_mask(affinity_mask: usize) -> Result<usize> {
40*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: trivially safe as return value is checked.
41*bb4ee6a4SAndroid Build Coastguard Worker     let res: usize = unsafe {
42*bb4ee6a4SAndroid Build Coastguard Worker         let thread_handle = GetCurrentThread();
43*bb4ee6a4SAndroid Build Coastguard Worker         SetThreadAffinityMask(thread_handle, affinity_mask)
44*bb4ee6a4SAndroid Build Coastguard Worker     };
45*bb4ee6a4SAndroid Build Coastguard Worker     if res == 0 {
46*bb4ee6a4SAndroid Build Coastguard Worker         return errno_result::<usize>();
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker     Ok(res)
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker 
get_cpu_affinity() -> Result<Vec<usize>>51*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_cpu_affinity() -> Result<Vec<usize>> {
52*bb4ee6a4SAndroid Build Coastguard Worker     // Unimplemented for now, since this is unused on Windows.  Thread affinity can be read by
53*bb4ee6a4SAndroid Build Coastguard Worker     // calling GetThreadAffinityMask twice, to get and restore the previous affinities.
54*bb4ee6a4SAndroid Build Coastguard Worker     Err(Error::new(EINVAL))
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
58*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
59*bb4ee6a4SAndroid Build Coastguard Worker     use winapi::um::processthreadsapi::GetCurrentProcess;
60*bb4ee6a4SAndroid Build Coastguard Worker     use winapi::um::winbase::GetProcessAffinityMask;
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker     use super::super::sched::*;
63*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cpu_affinity()64*bb4ee6a4SAndroid Build Coastguard Worker     fn cpu_affinity() {
65*bb4ee6a4SAndroid Build Coastguard Worker         let mut process_affinity_mask: usize = 0;
66*bb4ee6a4SAndroid Build Coastguard Worker         let mut system_affinity_mask: usize = 0;
67*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: trivially safe as return value is checked.
68*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe {
69*bb4ee6a4SAndroid Build Coastguard Worker             GetProcessAffinityMask(
70*bb4ee6a4SAndroid Build Coastguard Worker                 GetCurrentProcess(),
71*bb4ee6a4SAndroid Build Coastguard Worker                 &mut process_affinity_mask as *mut usize,
72*bb4ee6a4SAndroid Build Coastguard Worker                 &mut system_affinity_mask as *mut usize,
73*bb4ee6a4SAndroid Build Coastguard Worker             )
74*bb4ee6a4SAndroid Build Coastguard Worker         };
75*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(res, 0);
76*bb4ee6a4SAndroid Build Coastguard Worker         let mut prev_thread_affinity = set_cpu_affinity(vec![0, 1]).unwrap();
77*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(process_affinity_mask, prev_thread_affinity);
78*bb4ee6a4SAndroid Build Coastguard Worker         // reset to original process affinity and grab previous affinity.
79*bb4ee6a4SAndroid Build Coastguard Worker         prev_thread_affinity = set_cpu_affinity_mask(process_affinity_mask).unwrap();
80*bb4ee6a4SAndroid Build Coastguard Worker         // cpu 0 + cpu 1, means bit 0 and bit 1 are set (1 + 2 = 3). Verify that is the case.
81*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(prev_thread_affinity, 3);
82*bb4ee6a4SAndroid Build Coastguard Worker     }
83*bb4ee6a4SAndroid Build Coastguard Worker }
84