Skip to main content

VirtqProducer

Struct VirtqProducer 

Source
pub struct VirtqProducer<M, N, P> { /* private fields */ }
Expand description

A high-level virtqueue producer (driver side).

The producer sends chains to the consumer (device), and receives used chains. This is used on the driver/guest side.

§Threading

The producer is intended for single-threaded, guest-side use. Reply payloads are exposed as zero-copy Bytes via Bytes::from_owner, which requires the owning pool to be Send. Do not move the producer or its replies across threads, and do not instantiate it on the multi-threaded host with those pools.

§Example

let mut producer = VirtqProducer::new(layout, mem, notifier, pool);

// Build and submit a chain
let mut chain = producer.chain().readable(64).writable(64).build()?;
chain.write_all(b"hello")?;
let token = producer.submit(chain)?;

// Later, poll for the used chain
if let Some(used) = producer.poll()? {
    assert_eq!(used.token(), token);
    match used {
        UsedChain::Data(_, segments) => println!("Got used chain: {:?}", segments),
        UsedChain::Ack(_) => println!("Got ack"),
    }
}

Implementations§

Source§

impl<M, N, P> VirtqProducer<M, N, P>
where M: MemOps + Clone, N: Notifier, P: BufferProvider + Clone,

Source

pub fn new(layout: Layout, mem: M, notifier: N, pool: P) -> Self

Create a new virtqueue producer.

§Arguments
  • layout - Ring memory layout (descriptor table and event suppression addresses)
  • mem - Memory operations implementation for reading/writing to shared memory
  • notifier - Callback for notifying the device (consumer) about new chains
  • pool - Buffer allocator for chain payload and reply data
Source

pub fn chain(&self) -> ChainBuilder<M, P>

Begin building a descriptor chain for submission.

Returns a ChainBuilder that allocates buffers from the pool.

Source

pub fn batch(&mut self) -> SubmitBatch<'_, M, N, P>

Begin a batch of submissions.

Chains submitted through the returned SubmitBatch are published to the ring immediately, but the consumer is notified at most once when SubmitBatch::finish is called. This mirrors the virtio pattern of adding multiple buffers and then kicking the queue once.

Source

pub fn submit(&mut self, chain: SendChain<M, P>) -> Result<Token, VirtqError>

Submit a SendChain to the ring.

Publishes the descriptor chain, stores the in-flight tracking state, and notifies the consumer if event suppression allows. Notifications are layout-neutral; use batch when a higher-level protocol wants to publish multiple chains and kick once.

§Errors
Source

pub fn notify_backpressure(&self)

Signal backpressure to the consumer.

Bypasses event suppression. Call this when submit fails with a backpressure error and the consumer needs to drain.

Source

pub fn used_cursor(&self) -> RingCursor

Get the current used cursor position.

Useful for setting up descriptor-based event suppression.

Source

pub fn num_free(&self) -> usize

Number of free (unsubmitted) descriptors in the ring.

Source

pub fn set_used_suppression( &mut self, kind: SuppressionKind, ) -> Result<(), VirtqError>

Configure event suppression for used buffer notifications.

This controls when the device (consumer) signals us about completed buffers:

§Example: Used-chain batching
// Submit chains, then suppress notifications until all are used
let mut se = producer.chain().readable(64).writable(128).build()?;
se.write_all(b"entry1")?;
producer.submit(se)?;
let cursor = producer.used_cursor();
producer.set_used_suppression(SuppressionKind::Descriptor(cursor))?;
// Device will notify only after reaching that cursor position
Source

pub unsafe fn reset(&mut self)

Reset ring, inflight, and pool state to initial values.

§Safety

No outstanding UsedChain::Data buffers, borrowed segment views, or peer accesses to previously submitted descriptors may exist. Resetting recycles the same backing addresses, so outstanding zero-copy buffers or stale descriptor users could alias memory that is handed out again.

TODO(virtq): find a way to allow guest to keep used chains across resets.

Source

pub unsafe fn reset_with_pool(&mut self, pool: P)

Replace the pool and reset ring, inflight, and pending state.

§Safety

No outstanding UsedChain::Data buffers, borrowed segment views, or peer accesses to previously submitted descriptors may exist. The new pool may manage the same shared-memory addresses as the old pool, so old zero-copy buffers must not outlive this transition.

Source§

impl<M, N, P> VirtqProducer<M, N, P>
where M: MemOps + Clone + Send + 'static, N: Notifier, P: BufferProvider + Clone + Send + 'static,

Source

pub fn poll(&mut self) -> Result<Option<UsedChain>, VirtqError>

Poll for a single used chain from the device.

Returns buffered used chains from prior reclaim calls first, then checks the ring for newly used chains.

Returns Ok(Some(used)) if a used chain is available, Ok(None) if no used chains are ready (would block), or an error if the device misbehaved.

Data used chains contain zero-copy Bytes backed by the shared-memory allocation via BufferOwner. The pool allocation is held alive as long as any Bytes clone exists, and is returned to the pool when the last clone is dropped.

§Errors
Source

pub fn reclaim(&mut self) -> Result<usize, VirtqError>

Reclaim ring slots and pool allocations from used descriptors.

Processes all available used chains from the ring: frees readable buffer allocations immediately, and buffers writable data for later retrieval via poll.

Read-only ack used chains are discarded immediately.

Use this to free resources under backpressure without losing writable data. Returns the number of chains reclaimed.

Source

pub fn drain(&mut self, f: impl FnMut(UsedChain)) -> Result<(), VirtqError>

Drain all available used chains, calling the provided closure for each.

This is a convenience method that repeatedly calls poll until no more used chains are available.

§Arguments
  • f - Closure called for each used chain
§Example
producer.drain(|used| {
    println!("Got used chain for {:?}", used.token());
})?;

Auto Trait Implementations§

§

impl<M, N, P> Freeze for VirtqProducer<M, N, P>
where N: Freeze, P: Freeze, M: Freeze,

§

impl<M, N, P> RefUnwindSafe for VirtqProducer<M, N, P>

§

impl<M, N, P> Send for VirtqProducer<M, N, P>
where N: Send, P: Send, M: Send,

§

impl<M, N, P> Sync for VirtqProducer<M, N, P>
where N: Sync, P: Sync, M: Sync,

§

impl<M, N, P> Unpin for VirtqProducer<M, N, P>
where N: Unpin, P: Unpin, M: Unpin,

§

impl<M, N, P> UnsafeUnpin for VirtqProducer<M, N, P>

§

impl<M, N, P> UnwindSafe for VirtqProducer<M, N, P>
where N: UnwindSafe, P: UnwindSafe, M: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more