io_uring_mmap 1.0.0

internal crate
Documentation
#![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(())
}