Skip to content

Commit db22b95

Browse files
committed
Add SubmissionQueue::push_opcode()/push_multiple_opcode()
Add SubmissionQueue::push_opcode()/push_multiple_opcode() to generate SQE in place. Signed-off-by: Liu Jiang <[email protected]>
1 parent 8f8f609 commit db22b95

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

src/squeue.rs

+105
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::error::Error;
55
use std::fmt::{self, Display, Formatter};
66
use std::sync::atomic;
77

8+
use crate::opcode::PrepareSQE;
89
use crate::sys;
910
use crate::util::{unsync_load, Mmap};
1011

@@ -43,6 +44,14 @@ pub struct SubmissionQueue<'a> {
4344
#[derive(Clone)]
4445
pub struct Entry(pub(crate) sys::io_uring_sqe);
4546

47+
/// Common options for Submission Queue Entry.
48+
#[derive(Clone, Copy, Default, Debug)]
49+
pub struct OptionValues {
50+
user_data: u64,
51+
personality: u16,
52+
flags: u8,
53+
}
54+
4655
bitflags! {
4756
/// Submission flags
4857
pub struct Flags: u8 {
@@ -269,6 +278,64 @@ impl SubmissionQueue<'_> {
269278
Ok(())
270279
}
271280

281+
/// Attempts to push an opcode into the submission queue.
282+
/// If the queue is full, an error is returned.
283+
///
284+
/// # Safety
285+
///
286+
/// Developers must ensure that parameters of the opcode (such as buffer) are valid and will
287+
/// be valid for the entire duration of the operation, otherwise it may cause memory problems.
288+
#[inline]
289+
pub unsafe fn push_opcode<'a, T: PrepareSQE>(
290+
&'a mut self,
291+
opcode: &T,
292+
options: Option<&OptionValues>,
293+
) -> Result<(), PushError> {
294+
if !self.is_full() {
295+
let sqe = self.next_sqe();
296+
opcode.prepare(sqe);
297+
options.map(|o| Self::set_sqe_options(sqe, o));
298+
Ok(())
299+
} else {
300+
Err(PushError)
301+
}
302+
}
303+
304+
/// Attempts to push several opcodes into the queue.
305+
/// If the queue does not have space for all of the entries, an error is returned.
306+
///
307+
/// # Safety
308+
///
309+
/// Developers must ensure that parameters of all the entries (such as buffer) are valid and
310+
/// will be valid for the entire duration of the operation, otherwise it may cause memory
311+
/// problems.
312+
#[cfg(feature = "unstable")]
313+
#[inline]
314+
pub unsafe fn push_multiple_opcode<'a, T: PrepareSQE>(
315+
&'a mut self,
316+
ops: &[(T, Option<&OptionValues>)],
317+
) -> Result<(), PushError> {
318+
if self.capacity() - self.len() < ops.len() {
319+
return Err(PushError);
320+
}
321+
322+
for (opcode, options) in ops {
323+
let sqe = self.next_sqe();
324+
opcode.prepare(sqe);
325+
options.map(|o| Self::set_sqe_options(sqe, o));
326+
self.move_forward();
327+
}
328+
329+
Ok(())
330+
}
331+
332+
#[inline]
333+
fn set_sqe_options(sqe: &mut sys::io_uring_sqe, options: &OptionValues) {
334+
sqe.user_data = options.user_data;
335+
sqe.personality = options.personality;
336+
sqe.flags = options.flags;
337+
}
338+
272339
#[inline]
273340
fn next_sqe(&mut self) -> &mut sys::io_uring_sqe {
274341
// Safe because we are accessing an entry in the allocated submission queue.
@@ -320,6 +387,44 @@ impl Entry {
320387
}
321388
}
322389

390+
impl OptionValues {
391+
/// Create a new instance of `OptionValues`.
392+
pub fn new(user_data: u64, personality: u16, flags: Flags) -> Self {
393+
OptionValues {
394+
user_data,
395+
personality,
396+
flags: flags.bits(),
397+
}
398+
}
399+
400+
/// Set the user data.
401+
///
402+
/// This is an application-supplied value that will be passed straight through into the
403+
/// [completion queue entry](crate::cqueue::Entry::user_data).
404+
#[inline]
405+
pub fn user_data(mut self, user_data: u64) -> Self {
406+
self.user_data = user_data;
407+
self
408+
}
409+
410+
/// Set the personality of this event.
411+
///
412+
/// You can obtain a personality using
413+
/// [`Submitter::register_personality`](crate::Submitter::register_personality).
414+
#[inline]
415+
pub fn personality(mut self, personality: u16) -> Self {
416+
self.personality = personality;
417+
self
418+
}
419+
420+
/// Set the submission event's [flags](Flags).
421+
#[inline]
422+
pub fn flags(mut self, flags: Flags) -> Self {
423+
self.flags |= flags.bits();
424+
self
425+
}
426+
}
427+
323428
/// An error pushing to the submission queue due to it being full.
324429
#[derive(Debug, Clone, PartialEq, Eq)]
325430
#[non_exhaustive]

0 commit comments

Comments
 (0)