use std::io;
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::Arc;
use rdma_io_sys::ibverbs::*;
use crate::Result;
use crate::device::Context;
use crate::error::from_ptr;
pub struct CompletionChannel {
inner: *mut ibv_comp_channel,
_ctx: Arc<Context>,
}
unsafe impl Send for CompletionChannel {}
unsafe impl Sync for CompletionChannel {}
impl CompletionChannel {
pub fn new(ctx: &Arc<Context>) -> Result<Self> {
let ch = from_ptr(unsafe { ibv_create_comp_channel(ctx.inner) })?;
let fd = unsafe { (*ch).fd };
set_nonblocking(fd)?;
Ok(Self {
inner: ch,
_ctx: Arc::clone(ctx),
})
}
pub fn fd(&self) -> RawFd {
unsafe { (*self.inner).fd }
}
pub(crate) fn as_raw(&self) -> *mut ibv_comp_channel {
self.inner
}
pub fn get_cq_event(&self) -> Result<*mut ibv_cq> {
let mut cq: *mut ibv_cq = std::ptr::null_mut();
let mut ctx: *mut core::ffi::c_void = std::ptr::null_mut();
let ret = unsafe { ibv_get_cq_event(self.inner, &mut cq, &mut ctx) };
if ret != 0 {
Err(crate::Error::Verbs(io::Error::last_os_error()))
} else {
Ok(cq)
}
}
}
impl AsRawFd for CompletionChannel {
fn as_raw_fd(&self) -> RawFd {
self.fd()
}
}
impl Drop for CompletionChannel {
fn drop(&mut self) {
let ret = unsafe { ibv_destroy_comp_channel(self.inner) };
if ret != 0 {
tracing::error!(
"ibv_destroy_comp_channel failed: {}",
io::Error::from_raw_os_error(-ret)
);
}
}
}
fn set_nonblocking(fd: RawFd) -> Result<()> {
let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if flags < 0 {
return Err(crate::Error::Verbs(io::Error::last_os_error()));
}
let ret = unsafe { libc::fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK) };
if ret < 0 {
return Err(crate::Error::Verbs(io::Error::last_os_error()));
}
Ok(())
}