xref: /DragonOS/kernel/src/libs/cpumask.rs (revision 8cb2e9b344230227fe5f3ab3ebeb2522f1c5e289)
17d66c313SLoGin use bitmap::{traits::BitMapOps, AllocBitmap};
27d66c313SLoGin 
3e2841179SLoGin use crate::{mm::percpu::PerCpu, smp::cpu::ProcessorId};
47d66c313SLoGin 
5e2841179SLoGin #[derive(Clone)]
67d66c313SLoGin pub struct CpuMask {
77d66c313SLoGin     bmp: AllocBitmap,
87d66c313SLoGin }
97d66c313SLoGin 
107d66c313SLoGin #[allow(dead_code)]
117d66c313SLoGin impl CpuMask {
127d66c313SLoGin     pub fn new() -> Self {
13e2841179SLoGin         let bmp = AllocBitmap::new(PerCpu::MAX_CPU_NUM as usize);
147d66c313SLoGin         Self { bmp }
157d66c313SLoGin     }
167d66c313SLoGin 
177d66c313SLoGin     /// 获取CpuMask中的第一个cpu
18e2841179SLoGin     pub fn first(&self) -> Option<ProcessorId> {
19e2841179SLoGin         self.bmp
20e2841179SLoGin             .first_index()
21e2841179SLoGin             .map(|index| ProcessorId::new(index as u32))
227d66c313SLoGin     }
237d66c313SLoGin 
247d66c313SLoGin     /// 获取CpuMask中第一个未被置位的cpu
25e2841179SLoGin     pub fn first_zero(&self) -> Option<ProcessorId> {
26e2841179SLoGin         self.bmp
27e2841179SLoGin             .first_false_index()
28e2841179SLoGin             .map(|index| ProcessorId::new(index as u32))
297d66c313SLoGin     }
307d66c313SLoGin 
317d66c313SLoGin     /// 获取CpuMask中的最后一个被置位的cpu
32e2841179SLoGin     pub fn last(&self) -> Option<ProcessorId> {
33e2841179SLoGin         self.bmp
34e2841179SLoGin             .last_index()
35e2841179SLoGin             .map(|index| ProcessorId::new(index as u32))
367d66c313SLoGin     }
377d66c313SLoGin 
387d66c313SLoGin     /// 获取指定cpu之后第一个为1的位的cpu
39e2841179SLoGin     pub fn next_index(&self, cpu: ProcessorId) -> Option<ProcessorId> {
40e2841179SLoGin         self.bmp
41e2841179SLoGin             .next_index(cpu.data() as usize)
42e2841179SLoGin             .map(|index| ProcessorId::new(index as u32))
437d66c313SLoGin     }
447d66c313SLoGin 
457d66c313SLoGin     /// 获取指定cpu之后第一个为未被置位的cpu
46e2841179SLoGin     pub fn next_zero_index(&self, cpu: ProcessorId) -> Option<ProcessorId> {
47e2841179SLoGin         self.bmp
48e2841179SLoGin             .next_false_index(cpu.data() as usize)
49e2841179SLoGin             .map(|index| ProcessorId::new(index as u32))
50e2841179SLoGin     }
51e2841179SLoGin 
52e2841179SLoGin     pub fn set(&mut self, cpu: ProcessorId, value: bool) -> Option<bool> {
53e2841179SLoGin         self.bmp.set(cpu.data() as usize, value)
54e2841179SLoGin     }
55e2841179SLoGin 
56e2841179SLoGin     pub fn get(&self, cpu: ProcessorId) -> Option<bool> {
57e2841179SLoGin         self.bmp.get(cpu.data() as usize)
58e2841179SLoGin     }
59e2841179SLoGin 
60e2841179SLoGin     pub fn is_empty(&self) -> bool {
61e2841179SLoGin         self.bmp.is_empty()
627d66c313SLoGin     }
637d66c313SLoGin 
647d66c313SLoGin     /// 迭代所有被置位的cpu
657d66c313SLoGin     pub fn iter_cpu(&self) -> CpuMaskIter {
667d66c313SLoGin         CpuMaskIter {
677d66c313SLoGin             mask: self,
68*8cb2e9b3SLoGin             index: None,
697d66c313SLoGin             set: true,
70*8cb2e9b3SLoGin             begin: true,
717d66c313SLoGin         }
727d66c313SLoGin     }
737d66c313SLoGin 
747d66c313SLoGin     /// 迭代所有未被置位的cpu
757d66c313SLoGin     pub fn iter_zero_cpu(&self) -> CpuMaskIter {
767d66c313SLoGin         CpuMaskIter {
777d66c313SLoGin             mask: self,
78*8cb2e9b3SLoGin             index: None,
797d66c313SLoGin             set: false,
80*8cb2e9b3SLoGin             begin: true,
817d66c313SLoGin         }
827d66c313SLoGin     }
837d66c313SLoGin }
847d66c313SLoGin 
857d66c313SLoGin pub struct CpuMaskIter<'a> {
867d66c313SLoGin     mask: &'a CpuMask,
87*8cb2e9b3SLoGin     index: Option<ProcessorId>,
887d66c313SLoGin     set: bool,
89*8cb2e9b3SLoGin     begin: bool,
907d66c313SLoGin }
917d66c313SLoGin 
927d66c313SLoGin impl<'a> Iterator for CpuMaskIter<'a> {
93e2841179SLoGin     type Item = ProcessorId;
947d66c313SLoGin 
95e2841179SLoGin     fn next(&mut self) -> Option<ProcessorId> {
96*8cb2e9b3SLoGin         if self.index.is_none() && self.begin {
977d66c313SLoGin             if self.set {
98*8cb2e9b3SLoGin                 self.index = self.mask.first();
997d66c313SLoGin             } else {
100*8cb2e9b3SLoGin                 self.index = self.mask.first_zero();
1017d66c313SLoGin             }
1027d66c313SLoGin 
103*8cb2e9b3SLoGin             self.begin = false;
1047d66c313SLoGin         }
105*8cb2e9b3SLoGin         let result = self.index;
106*8cb2e9b3SLoGin         if self.set {
107*8cb2e9b3SLoGin             self.index = self.mask.next_index(self.index?);
108*8cb2e9b3SLoGin         } else {
109*8cb2e9b3SLoGin             self.index = self.mask.next_zero_index(self.index?);
110*8cb2e9b3SLoGin         }
111*8cb2e9b3SLoGin 
112*8cb2e9b3SLoGin         result
1137d66c313SLoGin     }
1147d66c313SLoGin }
115e2841179SLoGin 
116e2841179SLoGin impl core::fmt::Debug for CpuMask {
117e2841179SLoGin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118e2841179SLoGin         f.debug_struct("CpuMask")
119e2841179SLoGin             .field("bmp", &format!("size: {}", self.bmp.size()))
120e2841179SLoGin             .finish()
121e2841179SLoGin     }
122e2841179SLoGin }
123