#![doc(html_root_url = "https://docs.rs/jemalloc-ctl/0.1")]
#![warn(missing_docs)]
use std::os::raw::{c_char, c_int, c_void};
use std::io;
use std::mem;
use std::ptr;
use std::ffi::CStr;
pub mod arenas;
pub mod config;
pub mod opt;
pub mod stats;
pub mod stats_print;
pub mod thread;
extern "C" {
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_mallctlnametomib")]
fn mallctlnametomib(name: *const c_char, mibp: *mut usize, miblenp: *mut usize) -> c_int;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_mallctlbymib")]
fn mallctlbymib(
mib: *const usize,
miblen: usize,
oldp: *mut c_void,
oldlenp: *mut usize,
newp: *mut c_void,
newlen: usize,
) -> c_int;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_malloc_stats_print")]
fn malloc_stats_print(
write_cb: Option<unsafe extern "C" fn(*mut c_void, *const c_char)>,
cbopaque: *mut c_void,
opts: *const c_char,
);
}
unsafe fn name_to_mib(name: &str, mib: &mut [usize]) -> io::Result<()> {
debug_assert!(name.ends_with("\0"));
let mut len = mib.len();
cvt(mallctlnametomib(
name.as_ptr() as *const _,
mib.as_mut_ptr(),
&mut len,
))?;
debug_assert_eq!(mib.len(), len);
Ok(())
}
unsafe fn get<T>(mib: &[usize]) -> io::Result<T> {
let mut value = mem::uninitialized::<T>();
let mut len = mem::size_of::<T>();
cvt(mallctlbymib(
mib.as_ptr(),
mib.len(),
&mut value as *mut _ as *mut _,
&mut len,
ptr::null_mut(),
0,
))?;
debug_assert_eq!(len, mem::size_of::<T>());
Ok(value)
}
unsafe fn get_str(mib: &[usize]) -> io::Result<&'static str> {
let ptr: *const c_char = get(mib)?;
let cstr = CStr::from_ptr(ptr);
cstr.to_str()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
unsafe fn get_set<T>(mib: &[usize], mut value: T) -> io::Result<T> {
let mut len = mem::size_of::<T>();
cvt(mallctlbymib(
mib.as_ptr(),
mib.len(),
&mut value as *mut _ as *mut _,
&mut len,
&mut value as *mut _ as *mut _,
len,
))?;
debug_assert_eq!(len, mem::size_of::<T>());
Ok(value)
}
fn cvt(ret: c_int) -> io::Result<()> {
if ret == 0 {
Ok(())
} else {
Err(io::Error::from_raw_os_error(ret as i32))
}
}
#[derive(Copy, Clone)]
pub struct Epoch([usize; 1]);
impl Epoch {
pub fn new() -> io::Result<Epoch> {
let mut mib = [0; 1];
unsafe {
name_to_mib("epoch\0", &mut mib)?;
}
Ok(Epoch(mib))
}
pub fn advance(&self) -> io::Result<u64> {
unsafe { get_set(&self.0, 1) }
}
}
#[derive(Copy, Clone)]
pub struct Version([usize; 1]);
impl Version {
pub fn new() -> io::Result<Version> {
let mut mib = [0; 1];
unsafe {
name_to_mib("version\0", &mut mib)?;
}
Ok(Version(mib))
}
pub fn get(&self) -> io::Result<&'static str> {
unsafe { get_str(&self.0) }
}
}