1use std::collections::BTreeMap;
6
7use crate::bpf_skel::*;
8use anyhow::Result;
9use scx_utils::Cpumask;
10use scx_utils::Topology;
11use std::sync::Arc;
12use std::sync::Mutex;
13
14#[derive(Clone, Debug)]
15pub struct Domain {
16 id: usize,
17 mask: Cpumask,
18 #[allow(clippy::arc_with_non_send_sync)]
21 pub ctx: Arc<Mutex<Option<*mut types::dom_ctx>>>,
22}
23
24impl Domain {
25 pub fn id(&self) -> usize {
27 self.id
28 }
29
30 pub fn mask(&self) -> Cpumask {
32 self.mask.clone()
33 }
34
35 pub fn mask_slice(&self) -> &[u64] {
38 self.mask.as_raw_slice()
39 }
40
41 pub fn weight(&self) -> usize {
43 self.mask.weight()
44 }
45
46 pub fn ctx(&self) -> Option<&types::dom_ctx> {
47 let domc = self.ctx.lock().unwrap();
48
49 match *domc {
53 Some(ptr) => Some(unsafe { &*(ptr) }),
54 None => None,
55 }
56 }
57}
58
59#[derive(Debug)]
60pub struct DomainGroup {
61 doms: BTreeMap<usize, Domain>,
62 dom_numa_map: BTreeMap<usize, usize>,
63 num_numa_nodes: usize,
64 span: Cpumask,
65}
66
67impl DomainGroup {
68 pub fn new(top: &Topology, cpumasks: &[String]) -> Result<Self> {
69 let mut span = Cpumask::new();
70 let mut dom_numa_map = BTreeMap::new();
71 let mut dom_id = 0;
76 let (doms, num_numa_nodes) = if !cpumasks.is_empty() {
77 let mut doms: BTreeMap<usize, Domain> = BTreeMap::new();
78 for mask_str in cpumasks.iter() {
79 let mask = Cpumask::from_str(mask_str)?;
80 span |= &mask;
81 doms.insert(
82 dom_id,
83 Domain {
84 id: dom_id,
85 mask,
86 ctx: Arc::new(Mutex::new(None)),
87 },
88 );
89 dom_numa_map.insert(dom_id, 0);
90 dom_id += 1;
91 }
92 (doms, 1)
93 } else {
94 let mut doms: BTreeMap<usize, Domain> = BTreeMap::new();
95 for (node_id, node) in &top.nodes {
96 for llc in node.llcs.values() {
97 let mask = llc.span.clone();
98 span |= &mask;
99 doms.insert(
100 dom_id,
101 Domain {
102 id: dom_id,
103 mask,
104 ctx: Arc::new(Mutex::new(None)),
105 },
106 );
107 dom_numa_map.insert(dom_id, *node_id);
108 dom_id += 1;
109 }
110 }
111 (doms, top.nodes.len())
112 };
113
114 Ok(Self {
115 doms,
116 dom_numa_map,
117 num_numa_nodes,
118 span,
119 })
120 }
121
122 pub fn numa_doms(&self, numa_id: &usize) -> Vec<Domain> {
123 let mut numa_doms = Vec::new();
124 for (d_id, n_id) in self.dom_numa_map.iter() {
126 if n_id == numa_id {
127 let dom = self.doms.get(d_id).unwrap();
128 numa_doms.push(dom.clone());
129 }
130 }
131
132 numa_doms
133 }
134
135 pub fn doms(&self) -> &BTreeMap<usize, Domain> {
136 &self.doms
137 }
138
139 pub fn nr_doms(&self) -> usize {
140 self.doms.len()
141 }
142
143 pub fn nr_nodes(&self) -> usize {
144 self.num_numa_nodes
145 }
146
147 pub fn dom_numa_id(&self, dom_id: &usize) -> Option<usize> {
148 self.dom_numa_map.get(dom_id).copied()
149 }
150
151 pub fn weight(&self) -> usize {
152 self.span.weight()
153 }
154}