Fix the algorithm error for recycling descriptors in VirtQueue

This commit is contained in:
LI Qing
2024-04-15 17:44:43 +08:00
committed by Tate, Hongliang Tian
parent b7131e721c
commit 349d7baa24

View File

@ -147,18 +147,19 @@ impl VirtQueue {
.unwrap(); .unwrap();
let mut descs = Vec::with_capacity(size as usize); let mut descs = Vec::with_capacity(size as usize);
descs.push(descriptor_ptr); descs.push(descriptor_ptr);
for i in 0..size as usize { for i in 0..size {
let mut desc = descs.get(i).unwrap().clone(); let mut desc = descs.get(i as usize).unwrap().clone();
desc.add(1); let next_i = i + 1;
descs.push(desc); if next_i != size {
field_ptr!(&desc, Descriptor, next).write(&next_i).unwrap();
desc.add(1);
descs.push(desc);
} else {
field_ptr!(&desc, Descriptor, next).write(&(0u16)).unwrap();
}
} }
let notify = transport.get_notify_ptr(idx).unwrap(); let notify = transport.get_notify_ptr(idx).unwrap();
// Link descriptors together.
for i in 0..(size - 1) {
let temp = descs.get(i as usize).unwrap();
field_ptr!(temp, Descriptor, next).write(&(i + 1)).unwrap();
}
field_ptr!(&avail_ring_ptr, AvailRing, flags) field_ptr!(&avail_ring_ptr, AvailRing, flags)
.write(&(0u16)) .write(&(0u16))
.unwrap(); .unwrap();
@ -319,6 +320,9 @@ impl VirtQueue {
/// Whether there is a used element that can pop. /// Whether there is a used element that can pop.
pub fn can_pop(&self) -> bool { pub fn can_pop(&self) -> bool {
// read barrier
fence(Ordering::SeqCst);
self.last_used_idx != field_ptr!(&self.used, UsedRing, idx).read().unwrap() self.last_used_idx != field_ptr!(&self.used, UsedRing, idx).read().unwrap()
} }
@ -333,26 +337,24 @@ impl VirtQueue {
fn recycle_descriptors(&mut self, mut head: u16) { fn recycle_descriptors(&mut self, mut head: u16) {
let origin_free_head = self.free_head; let origin_free_head = self.free_head;
self.free_head = head; self.free_head = head;
let last_free_head = if head == 0 {
self.queue_size - 1
} else {
head - 1
};
let temp_desc = &mut self.descs[last_free_head as usize];
field_ptr!(temp_desc, Descriptor, next)
.write(&head)
.unwrap();
loop { loop {
let desc = &mut self.descs[head as usize]; let desc = &mut self.descs[head as usize];
let flags: DescFlags = field_ptr!(desc, Descriptor, flags).read().unwrap(); // Sets the buffer address and length to 0
field_ptr!(desc, Descriptor, addr).write(&(0u64)).unwrap();
field_ptr!(desc, Descriptor, len).write(&(0u32)).unwrap();
self.num_used -= 1; self.num_used -= 1;
let flags: DescFlags = field_ptr!(desc, Descriptor, flags).read().unwrap();
if flags.contains(DescFlags::NEXT) { if flags.contains(DescFlags::NEXT) {
field_ptr!(desc, Descriptor, flags)
.write(&DescFlags::empty())
.unwrap();
head = field_ptr!(desc, Descriptor, next).read().unwrap(); head = field_ptr!(desc, Descriptor, next).read().unwrap();
} else { } else {
field_ptr!(desc, Descriptor, next) field_ptr!(desc, Descriptor, next)
.write(&origin_free_head) .write(&origin_free_head)
.unwrap(); .unwrap();
return; break;
} }
} }
} }
@ -364,8 +366,6 @@ impl VirtQueue {
if !self.can_pop() { if !self.can_pop() {
return Err(QueueError::NotReady); return Err(QueueError::NotReady);
} }
// read barrier
fence(Ordering::SeqCst);
let last_used_slot = self.last_used_idx & (self.queue_size - 1); let last_used_slot = self.last_used_idx & (self.queue_size - 1);
let element_ptr = { let element_ptr = {
@ -390,8 +390,6 @@ impl VirtQueue {
if !self.can_pop() { if !self.can_pop() {
return Err(QueueError::NotReady); return Err(QueueError::NotReady);
} }
// read barrier
fence(Ordering::SeqCst);
let last_used_slot = self.last_used_idx & (self.queue_size - 1); let last_used_slot = self.last_used_idx & (self.queue_size - 1);
let element_ptr = { let element_ptr = {