#![no_std]
#![allow(clippy::missing_safety_doc)]
use core::ffi::c_void;
use core::mem::size_of;
use core::ptr::null_mut;
use io_uring_header::{
io_uring_cqe, io_uring_params, io_uring_sqe, IORING_FEAT_SINGLE_MMAP, IORING_OFF_SQES,
IORING_OFF_SQ_RING,
};
use map_err::{map_ptr, map_val};
const PROT_READ: i32 = 0x1;
const PROT_WRITE: i32 = 0x2;
const MAP_SHARED: i32 = 0x1;
const MAP_POPULATE: i32 = 0x8000;
pub struct Mmap<T> {
ptr: *mut T,
len: usize,
}
impl<T> Mmap<T> {
pub unsafe fn get(&self, index: usize) -> *mut T {
self.ptr.add(index)
}
}
impl<T> Drop for Mmap<T> {
fn drop(&mut self) {
unsafe {
munmap(self.ptr, self.len).unwrap();
}
}
}
pub unsafe fn mmap_sq_cq(fd: i32, params: &io_uring_params) -> Result<Mmap<c_void>, i32> {
if params.features & IORING_FEAT_SINGLE_MMAP == 0 {
map_val(-38)?;
}
let sq_len = params.sq_off.array as usize + (params.sq_entries as usize * size_of::<u32>());
let cq_len =
params.cq_off.cqes as usize + (params.cq_entries as usize * size_of::<io_uring_cqe>());
let len = sq_len.max(cq_len);
let ptr = map_ptr(io_uring_syscall::mmap(
null_mut(),
len,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE,
fd,
IORING_OFF_SQ_RING as isize,
))?;
Ok(Mmap { ptr, len })
}
pub unsafe fn mmap_sqe(fd: i32, params: &io_uring_params) -> Result<Mmap<io_uring_sqe>, i32> {
let len = params.sq_entries as usize * size_of::<io_uring_sqe>();
let ptr = map_ptr(io_uring_syscall::mmap(
null_mut(),
len,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE,
fd,
IORING_OFF_SQES as isize,
))?;
Ok(Mmap {
ptr: ptr as *mut io_uring_sqe,
len,
})
}
pub unsafe fn munmap<T>(ptr: *mut T, len: usize) -> Result<(), i32> {
map_val(io_uring_syscall::munmap(ptr as *mut c_void, len))?;
Ok(())
}