use libc::{
c_int, c_long, c_uint, c_ulong, syscall, timespec, SYS_io_cancel, SYS_io_destroy, SYS_io_getevents,
SYS_io_setup, SYS_io_submit,
};
use std::{
io::{Error, Result},
os::fd::RawFd,
};
pub type ContextId = c_ulong;
#[allow(dead_code)]
pub mod opcode {
pub const PREAD: u16 = 0;
pub const PWRITE: u16 = 1;
pub const FSYNC: u16 = 2;
pub const FDSYNC: u16 = 3;
pub const POLL: u16 = 5;
pub const NOOP: u16 = 6;
pub const PREADV: u16 = 7;
pub const PWRITEV: u16 = 8;
}
#[allow(dead_code)]
pub mod flags {
pub const RESFD: u32 = 1 << 0;
pub const IOPRIO: u32 = 1 << 1;
}
#[derive(Debug, Clone, Copy, Default)]
#[repr(C)]
pub struct IoEvent {
pub data: u64,
pub obj: u64,
pub res: i64,
pub res2: i64,
}
#[derive(Debug, Clone, Copy, Default)]
#[repr(C)]
pub struct IoCb {
pub data: u64,
#[cfg(target_endian = "little")]
pub key: u32,
#[cfg(target_endian = "little")]
pub rw_flags: c_int,
#[cfg(target_endian = "big")]
pub rw_flags: c_int,
#[cfg(target_endian = "big")]
pub key: u32,
pub opcode: u16,
pub reqprio: i16,
pub fildes: RawFd,
pub buf: u64,
pub nbytes: u64,
pub offset: i64,
pub _reserved2: u64,
pub flags: u32,
pub resfd: RawFd,
}
impl IoCb {
pub fn new(opcode: u16, fildes: RawFd, buf: *mut u8, nbytes: u64) -> Self {
Self { opcode, fildes, buf: buf as usize as u64, nbytes, ..Default::default() }
}
pub fn with_resfd(mut self, resfd: RawFd) -> Self {
self.resfd = resfd;
self.flags |= flags::RESFD;
self
}
pub fn with_data(mut self, data: u64) -> Self {
self.data = data;
self
}
}
pub unsafe fn setup(nr_events: c_uint, ctx_idp: &mut ContextId) -> Result<()> {
match syscall(SYS_io_setup, nr_events, ctx_idp as *mut _) {
0 => Ok(()),
_ => Err(Error::last_os_error()),
}
}
pub unsafe fn destroy(ctx_id: ContextId) -> Result<()> {
match syscall(SYS_io_destroy, ctx_id) as c_int {
0 => Ok(()),
_ => Err(Error::last_os_error()),
}
}
pub unsafe fn submit(ctx_id: ContextId, nr: c_ulong, iocbpp: *mut *mut IoCb) -> Result<c_int> {
match syscall(SYS_io_submit, ctx_id, nr, iocbpp) as c_int {
-1 => Err(Error::last_os_error()),
n => Ok(n),
}
}
pub unsafe fn cancel(ctx_id: ContextId, iocb: *mut IoCb, result: *mut IoEvent) -> Result<()> {
match syscall(SYS_io_cancel, ctx_id, iocb, result) as c_int {
0 => Ok(()),
_ => Err(Error::last_os_error()),
}
}
pub unsafe fn getevents(
ctx_id: ContextId, min_nr: c_long, nr: c_long, events: *mut IoEvent, timeout: *const timespec,
) -> Result<c_int> {
match syscall(SYS_io_getevents, ctx_id, min_nr, nr, events, timeout) as c_int {
-1 => Err(Error::last_os_error()),
n => Ok(n),
}
}