pub(crate) mod error;
mod ll;
mod thread;
use core::{ffi::c_int, fmt, ptr::NonNull};
use darwin_kperf_sys::kperfdata::kpep_db;
use self::error::try_kpc;
pub use self::{error::SamplerError, thread::ThreadSampler};
use crate::{
database::Database,
event::{Cpu, Event},
framework::{KPerf, KPerfData},
};
pub struct Sampler {
kperf: KPerf,
kperfdata: KPerfData,
db: NonNull<kpep_db>,
cpu: Cpu,
saved_force_all: c_int,
}
unsafe impl Send for Sampler {}
unsafe impl Sync for Sampler {}
impl fmt::Debug for Sampler {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Sampler")
.field("cpu", &self.cpu)
.finish_non_exhaustive()
}
}
impl Sampler {
pub fn new() -> Result<Self, SamplerError> {
self::ll::ll_init()
}
pub unsafe fn release(&self) -> Result<(), SamplerError> {
let kpc_vt = self.kperf.vtable();
let result = unsafe { (kpc_vt.kpc_force_all_ctrs_set)(self.saved_force_all) };
try_kpc(result, SamplerError::FailedToForceAllCounters)
}
#[must_use]
pub const fn kperf(&self) -> &KPerf {
&self.kperf
}
#[must_use]
pub const fn kperfdata(&self) -> &KPerfData {
&self.kperfdata
}
#[must_use]
pub const fn cpu(&self) -> Cpu {
self.cpu
}
#[must_use]
pub const fn database(&self) -> Database<'_> {
unsafe { Database::from_raw(&*self.db.as_ptr()) }
}
pub fn thread<const N: usize>(
&self,
events: [Event; N],
) -> Result<ThreadSampler<'_, N>, SamplerError> {
self::ll::ll_configure(self, events)
}
}
impl Drop for Sampler {
fn drop(&mut self) {
self::ll::ll_drop(self);
}
}