use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
use lock_api::{Mutex, RawMutex};
use crate::{KprobeAuxiliaryOps, KprobeOps, ProbePoint, UniProbe};
#[derive(Debug)]
pub struct ProbeManager<L: RawMutex + 'static, F: KprobeAuxiliaryOps> {
break_list: Mutex<L, BTreeMap<usize, Vec<UniProbe<L, F>>>>,
debug_list: Mutex<L, BTreeMap<usize, Vec<UniProbe<L, F>>>>,
}
impl<L: RawMutex + 'static, F: KprobeAuxiliaryOps> Default for ProbeManager<L, F> {
fn default() -> Self {
Self::new()
}
}
impl<L: RawMutex + 'static, F: KprobeAuxiliaryOps> ProbeManager<L, F> {
pub const fn new() -> Self {
ProbeManager {
break_list: Mutex::new(BTreeMap::new()),
debug_list: Mutex::new(BTreeMap::new()),
}
}
pub fn insert_probe(&self, probe: UniProbe<L, F>) {
let probe_point = probe.probe_point().clone();
self.insert_break_point(probe_point.break_address(), probe.clone());
self.insert_debug_point(probe_point.debug_address(), probe);
}
fn insert_break_point(&self, address: usize, probe: UniProbe<L, F>) {
let mut list = self.break_list.lock();
let list = list.entry(address).or_default();
list.push(probe);
}
fn insert_debug_point(&self, address: usize, probe: UniProbe<L, F>) {
let mut list = self.debug_list.lock();
let list = list.entry(address).or_default();
list.push(probe);
}
pub fn get_break_list(&self, address: usize) -> Option<Vec<UniProbe<L, F>>> {
self.break_list.lock().get(&address).cloned()
}
pub fn get_debug_list(&self, address: usize) -> Option<Vec<UniProbe<L, F>>> {
self.debug_list.lock().get(&address).cloned()
}
pub fn kprobe_num(&self, address: usize) -> usize {
self.break_list_len(address)
}
pub(crate) fn replace_debug_list_with_new_address(
&self,
old_address: usize,
new_address: usize,
) {
let mut debug_list = self.debug_list.lock();
if let Some(list) = debug_list.remove(&old_address) {
debug_list.insert(new_address, list);
}
}
#[inline]
fn break_list_len(&self, address: usize) -> usize {
self.break_list
.lock()
.get(&address)
.map(|list| list.len())
.unwrap_or(0)
}
pub fn remove_probe(&self, probe: UniProbe<L, F>) {
let probe_point = probe.probe_point();
self.remove_one_break(probe_point.break_address(), &probe);
self.remove_one_debug(probe_point.debug_address(), &probe);
}
fn remove_one_break(&self, address: usize, probe: &UniProbe<L, F>) {
let mut list = self.break_list.lock();
if let Some(list) = list.get_mut(&address) {
list.retain(|x| x != probe);
}
let len = list.get(&address).map(|list| list.len()).unwrap_or(0);
if len == 0 {
list.remove(&address);
}
}
fn remove_one_debug(&self, address: usize, probe: &UniProbe<L, F>) {
let mut list = self.debug_list.lock();
if let Some(list) = list.get_mut(&address) {
list.retain(|x| x != probe);
}
let len = list.get(&address).map(|list| list.len()).unwrap_or(0);
if len == 0 {
list.remove(&address);
}
}
}
pub type ProbePointList<F> = BTreeMap<usize, Arc<ProbePoint<F>>>;