vmbus_relay_intercept_device/
ring_buffer.rs1use safeatomic::AtomicSliceOps;
9use std::sync::atomic::AtomicU32;
10use user_driver::memory::MemoryBlock;
11use vmbus_ring::CONTROL_WORD_COUNT;
12use vmbus_ring::PAGE_SIZE;
13use vmbus_ring::RingMem;
14
15pub struct MemoryBlockRingBuffer(MemoryBlock);
16
17impl MemoryBlockRingBuffer {
18 pub fn new(mem: MemoryBlock) -> Self {
19 assert!(mem.len() >= 2 * PAGE_SIZE);
20 Self(mem)
21 }
22}
23
24impl From<MemoryBlock> for MemoryBlockRingBuffer {
25 fn from(mem: MemoryBlock) -> Self {
26 Self::new(mem)
27 }
28}
29
30impl RingMem for MemoryBlockRingBuffer {
31 fn len(&self) -> usize {
32 self.0.len() - PAGE_SIZE
33 }
34
35 fn read_at(&self, addr: usize, data: &mut [u8]) {
36 let addr = addr % self.len();
37 let initial_size = usize::min(data.len(), self.len() - addr);
38 self.0.read_at(addr + PAGE_SIZE, &mut data[..initial_size]);
39 if initial_size < data.len() {
40 self.0.read_at(PAGE_SIZE, &mut data[initial_size..]);
41 }
42 }
43
44 fn write_at(&self, addr: usize, data: &[u8]) {
45 let addr = addr % self.len();
46 let initial_size = usize::min(data.len(), self.len() - addr);
47 self.0.write_at(addr + PAGE_SIZE, &data[..initial_size]);
48 if initial_size < data.len() {
49 self.0.write_at(PAGE_SIZE, &data[initial_size..]);
50 }
51 }
52
53 fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT] {
54 self.0.as_slice().as_atomic_slice().unwrap()[..CONTROL_WORD_COUNT]
55 .try_into()
56 .unwrap()
57 }
58}