Skip to content

Commit db40491

Browse files
authored
feat: Support IORING_TIMEOUT_MULTISHOT flag (#332)
1 parent d504e99 commit db40491

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

io-uring-test/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ fn test<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
115115
tests::timeout::test_timeout_cancel(&mut ring, &test)?;
116116
tests::timeout::test_timeout_abs(&mut ring, &test)?;
117117
tests::timeout::test_timeout_submit_args(&mut ring, &test)?;
118+
tests::timeout::test_timeout_multishot(&mut ring, &test)?;
118119

119120
// net
120121
tests::net::test_tcp_write_read(&mut ring, &test)?;

io-uring-test/src/tests/timeout.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,54 @@ pub fn test_timeout_submit_args<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
381381

382382
Ok(())
383383
}
384+
385+
pub fn test_timeout_multishot<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
386+
ring: &mut IoUring<S, C>,
387+
test: &Test,
388+
) -> anyhow::Result<()> {
389+
require!(
390+
test;
391+
test.probe.is_supported(opcode::Timeout::CODE);
392+
);
393+
394+
println!("test timeout_multishot");
395+
396+
let ts = types::Timespec::new().sec(1);
397+
let timeout_e = opcode::Timeout::new(&ts)
398+
.flags(types::TimeoutFlags::MULTISHOT)
399+
.count(2);
400+
401+
unsafe {
402+
let mut queue = ring.submission();
403+
queue
404+
.push(&timeout_e.build().user_data(0x0c).into())
405+
.expect("queue is full");
406+
}
407+
408+
let start = Instant::now();
409+
ring.submit_and_wait(1)?;
410+
411+
assert_eq!(start.elapsed().as_secs(), 1);
412+
413+
let mut cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
414+
cqes.sort_by_key(|cqe| cqe.user_data());
415+
416+
assert_eq!(cqes.len(), 1);
417+
assert_eq!(cqes[0].user_data(), 0x0c);
418+
assert_eq!(cqes[0].result(), -libc::ETIME);
419+
assert!(cqueue::more(cqes[0].flags()));
420+
421+
ring.submit_and_wait(1)?;
422+
423+
assert_eq!(start.elapsed().as_secs(), 2);
424+
425+
let mut cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
426+
cqes.sort_by_key(|cqe| cqe.user_data());
427+
428+
assert_eq!(cqes.len(), 1);
429+
assert_eq!(cqes[0].user_data(), 0x0c);
430+
assert_eq!(cqes[0].result(), -libc::ETIME);
431+
assert!(!cqueue::more(cqes[0].flags()));
432+
433+
Ok(())
434+
}

src/opcode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,10 @@ opcode! {
543543
timespec: { *const types::Timespec },
544544
;;
545545
/// `count` may contain a completion event count.
546+
/// If [`TimeoutFlags::TIMEOUT`] is set in `flags`, this is the number of repeats. A value of 0 means the timeout is
547+
/// indefinite and can only be stopped by a removal request.
546548
count: u32 = 0,
547549

548-
/// `flags` may contain [types::TimeoutFlags::ABS] for an absolute timeout value, or 0 for a relative timeout.
549550
flags: types::TimeoutFlags = types::TimeoutFlags::empty()
550551
}
551552

src/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ bitflags! {
9999
const LINK_TIMEOUT_UPDATE = sys::IORING_LINK_TIMEOUT_UPDATE;
100100

101101
const ETIME_SUCCESS = sys::IORING_TIMEOUT_ETIME_SUCCESS;
102+
103+
const MULTISHOT = sys::IORING_TIMEOUT_MULTISHOT;
102104
}
103105
}
104106

0 commit comments

Comments
 (0)