use std::collections::BTreeMap;
use crate::bpf_skel::*;
use anyhow::Result;
use scx_utils::Cpumask;
use scx_utils::Topology;
use std::sync::Arc;
use std::sync::Mutex;
#[derive(Clone, Debug)]
pub struct Domain {
id: usize,
mask: Cpumask,
pub ctx: Arc<Mutex<Option<*mut types::dom_ctx>>>,
}
impl Domain {
pub fn id(&self) -> usize {
self.id
}
pub fn mask(&self) -> Cpumask {
self.mask.clone()
}
pub fn mask_slice(&self) -> &[u64] {
self.mask.as_raw_slice()
}
pub fn weight(&self) -> usize {
self.mask.weight()
}
pub fn ctx(&self) -> Option<&mut types::dom_ctx> {
let domc = self.ctx.lock().unwrap();
match *domc {
Some(ptr) => Some(unsafe { &mut *(ptr) }),
None => None,
}
}
}
#[derive(Debug)]
pub struct DomainGroup {
doms: BTreeMap<usize, Domain>,
dom_numa_map: BTreeMap<usize, usize>,
num_numa_nodes: usize,
span: Cpumask,
}
impl DomainGroup {
pub fn new(top: &Topology, cpumasks: &[String]) -> Result<Self> {
let mut span = Cpumask::new();
let mut dom_numa_map = BTreeMap::new();
let mut dom_id = 0;
let (doms, num_numa_nodes) = if !cpumasks.is_empty() {
let mut doms: BTreeMap<usize, Domain> = BTreeMap::new();
for mask_str in cpumasks.iter() {
let mask = Cpumask::from_str(mask_str)?;
span |= &mask;
doms.insert(
dom_id,
Domain {
id: dom_id,
mask,
ctx: Arc::new(Mutex::new(None)),
},
);
dom_numa_map.insert(dom_id, 0);
dom_id += 1;
}
(doms, 1)
} else {
let mut doms: BTreeMap<usize, Domain> = BTreeMap::new();
for (node_id, node) in &top.nodes {
for (_, llc) in node.llcs.iter() {
let mask = llc.span.clone();
span |= &mask;
doms.insert(
dom_id,
Domain {
id: dom_id,
mask,
ctx: Arc::new(Mutex::new(None)),
},
);
dom_numa_map.insert(dom_id, *node_id);
dom_id += 1;
}
}
(doms, top.nodes.len())
};
Ok(Self {
doms,
dom_numa_map,
num_numa_nodes,
span,
})
}
pub fn numa_doms(&self, numa_id: &usize) -> Vec<Domain> {
let mut numa_doms = Vec::new();
for (d_id, n_id) in self.dom_numa_map.iter() {
if n_id == numa_id {
let dom = self.doms.get(d_id).unwrap();
numa_doms.push(dom.clone());
}
}
numa_doms
}
pub fn doms(&self) -> &BTreeMap<usize, Domain> {
&self.doms
}
pub fn nr_doms(&self) -> usize {
self.doms.len()
}
pub fn nr_nodes(&self) -> usize {
self.num_numa_nodes
}
pub fn dom_numa_id(&self, dom_id: &usize) -> Option<usize> {
self.dom_numa_map.get(dom_id).copied()
}
pub fn weight(&self) -> usize {
self.span.weight()
}
}