use crate::error::{MemError, Result};
pub fn pin_thread_arena(arena_index: u32) -> Result<u32> {
let narenas = read_narenas()?;
let target_arena = if (arena_index as usize) < narenas {
arena_index
} else {
create_arena()?
};
set_thread_arena(target_arena)?;
Ok(target_arena)
}
fn read_narenas() -> Result<usize> {
tikv_jemalloc_ctl::arenas::narenas::read()
.map(|v| v as usize)
.map_err(|e| MemError::Jemalloc(format!("failed to read narenas: {e:?}")))
}
fn create_arena() -> Result<u32> {
let arena_idx: u32 = unsafe { tikv_jemalloc_ctl::raw::read(b"arenas.create\0") }
.map_err(|e| MemError::Jemalloc(format!("failed to create arena: {e:?}")))?;
Ok(arena_idx)
}
fn set_thread_arena(arena: u32) -> Result<()> {
unsafe { tikv_jemalloc_ctl::raw::write(b"thread.arena\0", arena) }
.map_err(|e| MemError::Jemalloc(format!("failed to set thread arena: {e:?}")))?;
Ok(())
}
pub fn current_thread_arena() -> Result<u32> {
let arena: u32 = unsafe { tikv_jemalloc_ctl::raw::read(b"thread.arena\0") }
.map_err(|e| MemError::Jemalloc(format!("failed to read thread arena: {e:?}")))?;
Ok(arena)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pin_and_read_arena() {
let assigned = pin_thread_arena(0).unwrap();
assert_eq!(assigned, 0);
let current = current_thread_arena().unwrap();
assert_eq!(current, 0);
}
#[test]
fn create_and_pin_new_arena() {
let narenas = read_narenas().unwrap();
let assigned = pin_thread_arena(narenas as u32 + 100).unwrap();
let current = current_thread_arena().unwrap();
assert_eq!(current, assigned);
}
}