use std::io::{self, Error as IoError};
use std::ptr::NonNull;
use std::sync::Arc;
use std::{fmt, ptr};
use crate::bindings::*;
use crate::rdma::{context::Context, cq::Cq, mr::*, pd::Pd, qp::build_sgl};
use crate::utils::interop::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub(crate) struct IbvSrq(Option<NonNull<ibv_srq>>);
impl IbvSrq {
pub unsafe fn destroy(self) -> io::Result<()> {
let ret = ibv_destroy_srq(self.as_ptr());
from_c_ret(ret)
}
}
impl_ibv_wrapper_traits!(ibv_srq, IbvSrq);
struct SrqInner {
pd: Pd,
srq: IbvSrq,
num: u32,
}
impl Drop for SrqInner {
fn drop(&mut self) {
unsafe { self.srq.destroy() }.expect("cannot destroy SRQ on drop");
}
}
#[derive(Clone)]
pub struct Srq {
srq: IbvSrq,
inner: Arc<SrqInner>,
}
impl fmt::Debug for Srq {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("Srq<{:p}>", self.as_raw()))
}
}
impl Srq {
pub fn new(pd: &Pd, cq: Option<&Cq>, max_wr: u32, max_sge: u32) -> io::Result<Self> {
fn make_srq(pd: &Pd, _cq: Option<&Cq>, max_wr: u32, max_sge: u32) -> io::Result<IbvSrq> {
let mut init_attr = ibv_srq_init_attr {
srq_context: ptr::null_mut(),
attr: ibv_srq_attr {
max_wr,
max_sge,
srq_limit: 0,
},
};
let srq = unsafe { ibv_create_srq(pd.as_raw(), &mut init_attr) };
let srq = NonNull::new(srq).ok_or_else(IoError::last_os_error)?;
Ok(IbvSrq::from(srq))
}
let srq = make_srq(pd, cq, max_wr, max_sge)?;
let mut num = 0;
let ret = unsafe { ibv_get_srq_num(srq.as_ptr(), &mut num) };
from_c_ret(ret)?;
let srq = Srq {
inner: Arc::new(SrqInner {
pd: pd.clone(),
srq,
num,
}),
srq,
};
Ok(srq)
}
#[inline]
pub fn as_raw(&self) -> *mut ibv_srq {
self.srq.as_ptr()
}
pub fn pd(&self) -> &Pd {
&self.inner.pd
}
pub fn context(&self) -> &Context {
self.inner.pd.context()
}
pub fn srq_num(&self) -> u32 {
self.inner.num
}
pub fn recv(&self, local: &[MrSlice], wr_id: u64) -> io::Result<()> {
assert!(local.len() == 1);
let mut sgl = build_sgl(local);
let mut wr = ibv_recv_wr {
wr_id,
next: ptr::null_mut(),
sg_list: if local.is_empty() {
ptr::null_mut()
} else {
sgl.as_mut_ptr()
},
num_sge: local.len() as i32,
};
let ret = {
let mut bad_wr = ptr::null_mut();
unsafe { ibv_post_srq_recv(self.as_raw(), &mut wr, &mut bad_wr) }
};
from_c_ret(ret)
}
}