pub struct LockFreeRing {
size: usize,
frame_count: usize,
frames: Vec<PhysFrame>,
header: *mut RingHeader,
slots: *mut RingSlot,
capacity: u32,
slot_size: u32,
}Expand description
A lock-free single-producer single-consumer ring buffer.
§SPSC guarantee
write must only be called from the producer thread; read must
only be called from the consumer thread. No locks are used : only
atomic loads/stores with acquire/release ordering.
For multi-queue NIC RSS, create one LockFreeRing per RSS queue rather
than sharing a single MPSC ring; this avoids CAS contention and
head-of-line blocking.
Fields§
§size: usizeTotal size in bytes of the shared memory region.
frame_count: usizeNumber of physical frames backing the ring.
frames: Vec<PhysFrame>Physical frames.
header: *mut RingHeaderVirtual address of the header (first page).
slots: *mut RingSlotVirtual address of the first slot (immediately after the header in the first page, or in subsequent pages when slots spill over).
capacity: u32Number of slots (derived from capacity in the header).
slot_size: u32Slot size in bytes.
Implementations§
Source§impl LockFreeRing
impl LockFreeRing
Sourceconst DEFAULT_CAPACITY: u32 = 256
const DEFAULT_CAPACITY: u32 = 256
Default slot count (power of two).
Sourcepub fn new(slot_count: u32, slot_size: usize) -> Result<Arc<Self>, RingError>
pub fn new(slot_count: u32, slot_size: usize) -> Result<Arc<Self>, RingError>
Create a new ring with slot_count slots of slot_size bytes.
The ring is allocated from physically-contiguous DMA-accessible frames and zeroed. Returns an error if allocation fails.
Sourcepub fn frame_phys_addrs(&self) -> Vec<u64>
pub fn frame_phys_addrs(&self) -> Vec<u64>
Physical addresses of the backing frames (for DMA and for mapping into other address spaces via capabilities).
Sourcepub fn write(&self, data: &[u8]) -> Result<(), RingError>
pub fn write(&self, data: &[u8]) -> Result<(), RingError>
Write data into the ring. Returns Full if no slot is available,
or MessageTooLarge if the data exceeds the slot capacity.
§Ordering
- Non-atomic copy into the slot (
copy_nonoverlapping). len.store(Release): makes the length visible after data.tail.store(Release): publishes the slot.
On ARM/POWER the Release barrier on len prevents the consumer
from seeing len != 0 before the data stores are visible.
Sourcepub fn read(&self, buf: &mut [u8]) -> Result<usize, RingError>
pub fn read(&self, buf: &mut [u8]) -> Result<usize, RingError>
Read one message from the ring into buf.
Returns Empty if no message is available, or BufferTooSmall if
the waiting message is larger than buf.
Sourcepub fn try_write(&self, data: &[u8]) -> Result<(), RingError>
pub fn try_write(&self, data: &[u8]) -> Result<(), RingError>
Non-blocking write. Equivalent to write.
Sourcepub fn write_vectored(&self, bufs: &[&[u8]]) -> Result<(), RingError>
pub fn write_vectored(&self, bufs: &[&[u8]]) -> Result<(), RingError>
Write multiple buffers in a single slot (scatter-gather).
Concatenates bufs and writes them as one message.
Sourcepub fn try_read(&self, buf: &mut [u8]) -> Result<Option<usize>, RingError>
pub fn try_read(&self, buf: &mut [u8]) -> Result<Option<usize>, RingError>
Non-blocking read. Returns Ok(None) when the ring is empty.
Sourcepub fn notify_consumer_raw(&self)
pub fn notify_consumer_raw(&self)
Notify the consumer that new data is available (futex wake). Increments the consumer notification counter.
Sourcepub fn notify_producer_raw(&self)
pub fn notify_producer_raw(&self)
Notify the producer that space has been freed (futex wake). Increments the producer notification counter.
Sourcepub fn has_data(&self) -> bool
pub fn has_data(&self) -> bool
Query whether the consumer should wake. Returns true if data is
available (tail != head). Used after futex_wait returns.
Sourcepub fn has_space(&self) -> bool
pub fn has_space(&self) -> bool
Query whether the producer can write without blocking. Returns true if at least one slot is free.
Sourcepub fn dma_buffer(&self, slot_index: u32) -> DmaBuffer
pub fn dma_buffer(&self, slot_index: u32) -> DmaBuffer
Provide a DMA-accessible buffer descriptor for zero-copy NIC operation. The physical address points directly into the slot’s data area so the NIC can DMA into the ring without an intermediate copy.
fn head(&self) -> &AtomicU32
fn tail(&self) -> &AtomicU32
fn slot_at(&self, index: u32) -> *mut RingSlot
Trait Implementations§
Source§impl Debug for LockFreeRing
impl Debug for LockFreeRing
Source§impl Drop for LockFreeRing
impl Drop for LockFreeRing
Source§impl IpcConsumer for LockFreeRing
impl IpcConsumer for LockFreeRing
Source§impl IpcNotification for LockFreeRing
impl IpcNotification for LockFreeRing
Source§fn notify_consumer(&self)
fn notify_consumer(&self)
Source§fn notify_producer(&self)
fn notify_producer(&self)
Source§impl IpcProducer for LockFreeRing
impl IpcProducer for LockFreeRing
Source§impl IpcTransport for LockFreeRing
impl IpcTransport for LockFreeRing
Source§fn level(&self) -> TransportLevel
fn level(&self) -> TransportLevel
Source§fn capabilities(&self) -> TransportCapabilities
fn capabilities(&self) -> TransportCapabilities
impl Send for LockFreeRing
impl Sync for LockFreeRing
Auto Trait Implementations§
impl Freeze for LockFreeRing
impl RefUnwindSafe for LockFreeRing
impl Unpin for LockFreeRing
impl UnsafeUnpin for LockFreeRing
impl UnwindSafe for LockFreeRing
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more