From 279248255f9f65c6baf044f1fbff0011bcd9938a Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Thu, 7 Nov 2019 14:18:41 -0800 Subject: [PATCH] devices: virtio: add peek operation to queue This allows the caller to grab a buffer without committing to using it, which can be used in the case where two resources (a virtio buffer plus some other resource) need to be acquired simultaneously. BUG=None TEST=build_test.py Change-Id: Icb61de99db807648ff02c41f95b3128ecce41501 Signed-off-by: Daniel Verkamp Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1904638 Reviewed-by: Stephen Barber Tested-by: Stephen Barber Commit-Queue: Stephen Barber --- devices/src/virtio/queue.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/devices/src/virtio/queue.rs b/devices/src/virtio/queue.rs index 722a4ea9cc..78a9cc377d 100644 --- a/devices/src/virtio/queue.rs +++ b/devices/src/virtio/queue.rs @@ -295,8 +295,9 @@ impl Queue { } } - /// If a new DescriptorHead is available, returns one and removes it from the queue. - pub fn pop<'a>(&mut self, mem: &'a GuestMemory) -> Option> { + /// Get the first available descriptor chain without removing it from the queue. + /// Call `pop_peeked` to remove the returned descriptor chain from the queue. + pub fn peek<'a>(&mut self, mem: &'a GuestMemory) -> Option> { if !self.is_valid(mem) { return None; } @@ -316,10 +317,20 @@ impl Queue { // This index is checked below in checked_new. let descriptor_index: u16 = mem.read_obj_from_addr(desc_idx_addr).unwrap(); - let descriptor_chain = - DescriptorChain::checked_new(mem, self.desc_table, queue_size, descriptor_index, 0); + DescriptorChain::checked_new(mem, self.desc_table, queue_size, descriptor_index, 0) + } + + /// Remove the first available descriptor chain from the queue. + /// This function should only be called immediately following `peek`. + pub fn pop_peeked(&mut self) { + self.next_avail += Wrapping(1); + } + + /// If a new DescriptorHead is available, returns one and removes it from the queue. + pub fn pop<'a>(&mut self, mem: &'a GuestMemory) -> Option> { + let descriptor_chain = self.peek(mem); if descriptor_chain.is_some() { - self.next_avail += Wrapping(1); + self.pop_peeked(); } descriptor_chain }