1use std::num::Wrapping;
6use std::ops::Deref;
7use std::sync::atomic::Ordering;
8use std::sync::{Arc, Mutex, MutexGuard};
9
10use vm_memory::GuestMemory;
11
12use crate::{DescriptorChain, Error, Queue, QueueGuard, QueueT};
13
14#[derive(Clone, Debug)]
41pub struct QueueSync {
42 state: Arc<Mutex<Queue>>,
43}
44
45impl QueueSync {
46 fn lock_state(&self) -> MutexGuard<'_, Queue> {
47 self.state.lock().unwrap()
49 }
50}
51
52impl<'a> QueueGuard<'a> for QueueSync {
53 type G = MutexGuard<'a, Queue>;
54}
55
56impl QueueT for QueueSync {
57 fn new(max_size: u16) -> Result<Self, Error> {
58 Ok(QueueSync {
59 state: Arc::new(Mutex::new(Queue::new(max_size)?)),
60 })
61 }
62
63 fn is_valid<M: GuestMemory>(&self, mem: &M) -> bool {
64 self.lock_state().is_valid(mem)
65 }
66
67 fn reset(&mut self) {
68 self.lock_state().reset();
69 }
70
71 fn lock(&mut self) -> <Self as QueueGuard<'_>>::G {
72 self.lock_state()
73 }
74
75 fn max_size(&self) -> u16 {
76 self.lock_state().max_size()
77 }
78
79 fn size(&self) -> u16 {
80 self.lock_state().size()
81 }
82
83 fn set_size(&mut self, size: u16) {
84 self.lock_state().set_size(size);
85 }
86
87 fn ready(&self) -> bool {
88 self.lock_state().ready()
89 }
90
91 fn set_ready(&mut self, ready: bool) {
92 self.lock_state().set_ready(ready)
93 }
94
95 fn set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>) {
96 self.lock_state().set_desc_table_address(low, high);
97 }
98
99 fn set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
100 self.lock_state().set_avail_ring_address(low, high);
101 }
102
103 fn set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
104 self.lock_state().set_used_ring_address(low, high);
105 }
106
107 fn set_event_idx(&mut self, enabled: bool) {
108 self.lock_state().set_event_idx(enabled);
109 }
110
111 fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
112 where
113 M: GuestMemory + ?Sized,
114 {
115 self.lock_state().avail_idx(mem, order)
116 }
117
118 fn used_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
119 self.lock_state().used_idx(mem, order)
120 }
121
122 fn add_used<M: GuestMemory>(
123 &mut self,
124 mem: &M,
125 head_index: u16,
126 len: u32,
127 ) -> Result<(), Error> {
128 self.lock_state().add_used(mem, head_index, len)
129 }
130
131 fn enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> {
132 self.lock_state().enable_notification(mem)
133 }
134
135 fn disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error> {
136 self.lock_state().disable_notification(mem)
137 }
138
139 fn needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> {
140 self.lock_state().needs_notification(mem)
141 }
142
143 fn next_avail(&self) -> u16 {
144 self.lock_state().next_avail()
145 }
146
147 fn set_next_avail(&mut self, next_avail: u16) {
148 self.lock_state().set_next_avail(next_avail);
149 }
150
151 fn next_used(&self) -> u16 {
152 self.lock_state().next_used()
153 }
154
155 fn set_next_used(&mut self, next_used: u16) {
156 self.lock_state().set_next_used(next_used);
157 }
158
159 fn desc_table(&self) -> u64 {
160 self.lock_state().desc_table()
161 }
162
163 fn avail_ring(&self) -> u64 {
164 self.lock_state().avail_ring()
165 }
166
167 fn used_ring(&self) -> u64 {
168 self.lock_state().used_ring()
169 }
170
171 fn event_idx_enabled(&self) -> bool {
172 self.lock_state().event_idx_enabled()
173 }
174
175 fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
176 where
177 M: Clone + Deref,
178 M::Target: GuestMemory,
179 {
180 self.lock_state().pop_descriptor_chain(mem)
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187 use crate::defs::{DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR};
188 use std::sync::Barrier;
189 use virtio_bindings::bindings::virtio_ring::VRING_USED_F_NO_NOTIFY;
190 use vm_memory::{Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryMmap};
191
192 #[test]
193 fn test_queue_state_sync() {
194 let mut q = QueueSync::new(0x1000).unwrap();
195 let mut q2 = q.clone();
196 let q3 = q.clone();
197 let barrier = Arc::new(Barrier::new(3));
198 let b2 = barrier.clone();
199 let b3 = barrier.clone();
200
201 let t1 = std::thread::spawn(move || {
202 {
203 let guard = q2.lock();
204 assert!(!guard.ready());
205 }
206 b2.wait();
207 b2.wait();
208 {
209 let guard = q2.lock();
210 assert!(guard.ready());
211 }
212 });
213
214 let t2 = std::thread::spawn(move || {
215 assert!(!q3.ready());
216 b3.wait();
217 b3.wait();
218 assert!(q3.ready());
219 });
220
221 barrier.wait();
222 q.set_ready(true);
223 barrier.wait();
224
225 t1.join().unwrap();
226 t2.join().unwrap();
227 }
228
229 #[test]
230 fn test_state_sync_add_used() {
231 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
232 let mut q = QueueSync::new(0x100).unwrap();
233
234 q.set_desc_table_address(Some(0x1000), None);
235 q.set_avail_ring_address(Some(0x2000), None);
236 q.set_used_ring_address(Some(0x3000), None);
237 q.set_event_idx(true);
238 q.set_ready(true);
239 assert!(q.is_valid(m.memory()));
240 assert_eq!(q.lock().size(), 0x100);
241
242 assert_eq!(q.max_size(), 0x100);
243 assert_eq!(q.size(), 0x100);
244 q.set_size(0x80);
245 assert_eq!(q.size(), 0x80);
246 assert_eq!(q.max_size(), 0x100);
247 q.set_next_avail(5);
248 assert_eq!(q.next_avail(), 5);
249 q.set_next_used(3);
250 assert_eq!(q.next_used(), 3);
251 assert_eq!(
252 q.avail_idx(m.memory(), Ordering::Acquire).unwrap(),
253 Wrapping(0)
254 );
255 assert_eq!(
256 q.used_idx(m.memory(), Ordering::Acquire).unwrap(),
257 Wrapping(0)
258 );
259
260 assert_eq!(q.next_used(), 3);
261
262 assert!(q.add_used(m.memory(), 0x200, 0x1000).is_err());
264 assert_eq!(q.next_used(), 3);
265
266 q.add_used(m.memory(), 1, 0x1000).unwrap();
268 assert_eq!(q.next_used(), 4);
269 assert_eq!(
270 q.used_idx(m.memory(), Ordering::Acquire).unwrap(),
271 Wrapping(4)
272 );
273 }
274
275 #[test]
276 fn test_sync_state_reset_queue() {
277 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
278 let mut q = QueueSync::new(0x100).unwrap();
279
280 q.set_desc_table_address(Some(0x1000), None);
281 q.set_avail_ring_address(Some(0x2000), None);
282 q.set_used_ring_address(Some(0x3000), None);
283 q.set_event_idx(true);
284 q.set_next_avail(2);
285 q.set_next_used(2);
286 q.set_size(0x8);
287 q.set_ready(true);
288 assert!(q.is_valid(m.memory()));
289
290 q.needs_notification(m.memory()).unwrap();
291
292 assert_eq!(q.lock_state().size(), 0x8);
293 assert!(q.lock_state().ready());
294 assert_ne!(q.lock_state().desc_table(), DEFAULT_DESC_TABLE_ADDR);
295 assert_ne!(q.lock_state().avail_ring(), DEFAULT_AVAIL_RING_ADDR);
296 assert_ne!(q.lock_state().used_ring(), DEFAULT_USED_RING_ADDR);
297 assert_ne!(q.lock_state().next_avail(), 0);
298 assert_ne!(q.lock_state().next_used(), 0);
299 assert!(q.lock_state().event_idx_enabled());
300
301 q.reset();
302 assert_eq!(q.lock_state().size(), 0x100);
303 assert!(!q.lock_state().ready());
304 assert_eq!(q.lock_state().desc_table(), DEFAULT_DESC_TABLE_ADDR);
305 assert_eq!(q.lock_state().avail_ring(), DEFAULT_AVAIL_RING_ADDR);
306 assert_eq!(q.lock_state().used_ring(), DEFAULT_USED_RING_ADDR);
307 assert_eq!(q.lock_state().next_avail(), 0);
308 assert_eq!(q.lock_state().next_used(), 0);
309 assert!(!q.lock_state().event_idx_enabled());
310 }
311
312 #[test]
313 fn test_enable_disable_notification() {
314 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
315 let mem = m.memory();
316 let mut q = QueueSync::new(0x100).unwrap();
317
318 q.set_desc_table_address(Some(0x1000), None);
319 assert_eq!(q.desc_table(), 0x1000);
320 q.set_avail_ring_address(Some(0x2000), None);
321 assert_eq!(q.avail_ring(), 0x2000);
322 q.set_used_ring_address(Some(0x3000), None);
323 assert_eq!(q.used_ring(), 0x3000);
324 q.set_ready(true);
325 assert!(q.is_valid(mem));
326
327 let used_addr = GuestAddress(q.lock_state().used_ring());
328
329 assert!(!q.event_idx_enabled());
330 q.enable_notification(mem).unwrap();
331 let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
332 assert_eq!(v, 0);
333
334 q.disable_notification(m.memory()).unwrap();
335 let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
336 assert_eq!(v, VRING_USED_F_NO_NOTIFY as u16);
337
338 q.enable_notification(mem).unwrap();
339 let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
340 assert_eq!(v, 0);
341
342 q.set_event_idx(true);
343 let avail_addr = GuestAddress(q.lock_state().avail_ring());
344 m.write_obj::<u16>(u16::to_le(2), avail_addr.unchecked_add(2))
345 .unwrap();
346
347 assert!(q.enable_notification(mem).unwrap());
348 q.lock_state().set_next_avail(2);
349 assert!(!q.enable_notification(mem).unwrap());
350
351 m.write_obj::<u16>(u16::to_le(8), avail_addr.unchecked_add(2))
352 .unwrap();
353
354 assert!(q.enable_notification(mem).unwrap());
355 q.lock_state().set_next_avail(8);
356 assert!(!q.enable_notification(mem).unwrap());
357 }
358}