mod common;
use std::{ io, thread };
use std::sync::Arc;
use std::convert::TryInto;
use std::time::{ Duration, Instant };
use std::os::unix::io::AsRawFd;
use nix::sys::eventfd::*;
use io_uring::opcode::{ self, types };
use io_uring::IoUring;
use common::Fd;
#[test]
fn test_eventfd() -> anyhow::Result<()> {
let mut ring = IoUring::new(1)?;
let efd: Arc<Fd> = eventfd(0, EfdFlags::EFD_CLOEXEC)?
.try_into()
.map(Arc::new)
.map_err(|_| anyhow::format_err!("invalid fd"))?;
let mut buf = [0; 8];
let mut bufs = [io::IoSliceMut::new(&mut buf)];
let entry = {
let efd = types::Target::Fd(efd.as_raw_fd());
let bufs_ptr = bufs.as_mut_ptr() as *mut _;
opcode::Readv::new(efd, bufs_ptr, 1)
};
unsafe {
ring
.submission()
.available()
.push(entry.build().user_data(0x42))
.map_err(drop)
.expect("queue is full");
}
ring.submit()?;
let now = Instant::now();
let efd2 = efd.clone();
let handle = thread::spawn(move || {
thread::sleep(Duration::from_secs(1));
nix::unistd::write(efd2.as_raw_fd(), &0x1u64.to_le_bytes())?;
nix::unistd::write(efd2.as_raw_fd(), &0x1u64.to_le_bytes())?;
Ok(()) as anyhow::Result<()>
});
ring.submit_and_wait(1)?;
let t = now.elapsed();
assert_eq!(t.as_secs(), 1);
let entry = ring
.completion()
.available()
.next()
.expect("queue is empty");
assert_eq!(u64::from_le_bytes(buf), 2);
assert_eq!(entry.user_data(), 0x42);
handle.join().unwrap()?;
Ok(())
}