use rdma_mummy_sys::{ibv_dereg_mr, ibv_mr, ibv_reg_mr};
use std::{io, ptr::NonNull, sync::Arc};
use super::protection_domain::ProtectionDomain;
use super::AccessFlags;
#[derive(Debug, thiserror::Error)]
#[error("failed to register memory region")]
#[non_exhaustive]
pub struct RegisterMemoryRegionError(#[from] pub RegisterMemoryRegionErrorKind);
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
#[non_exhaustive]
pub enum RegisterMemoryRegionErrorKind {
Ibverbs(#[from] io::Error),
#[error("unexpected null pointer provided")]
UnexpectedNullPointer,
}
#[derive(Debug)]
pub struct MemoryRegion {
mr: NonNull<ibv_mr>,
_pd: Arc<ProtectionDomain>,
}
impl Drop for MemoryRegion {
fn drop(&mut self) {
unsafe {
ibv_dereg_mr(self.mr.as_mut());
}
}
}
impl MemoryRegion {
pub fn lkey(&self) -> u32 {
unsafe { self.mr.as_ref().lkey }
}
pub fn rkey(&self) -> u32 {
unsafe { self.mr.as_ref().rkey }
}
pub fn region_len(&self) -> usize {
unsafe { self.mr.as_ref().length }
}
pub fn get_ptr(&self) -> usize {
unsafe { self.mr.as_ref().addr as _ }
}
pub unsafe fn mr(&self) -> NonNull<ibv_mr> {
self.mr
}
}
impl MemoryRegion {
pub(crate) unsafe fn reg_mr(
pd: Arc<ProtectionDomain>, ptr: usize, len: usize, access: AccessFlags,
) -> Result<Self, RegisterMemoryRegionError> {
let mr = unsafe { ibv_reg_mr(pd.pd.as_ptr(), ptr as _, len, access.into()) };
if mr.is_null() {
return Err(RegisterMemoryRegionErrorKind::Ibverbs(io::Error::last_os_error()).into());
}
Ok(Self {
mr: NonNull::new(mr).unwrap(),
_pd: pd,
})
}
}
unsafe impl Send for MemoryRegion {}
unsafe impl Sync for MemoryRegion {}