@@ -197,6 +197,14 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
197
197
self . state . avail_idx ( self . mem . memory ( ) . deref ( ) , order)
198
198
}
199
199
200
+ /// Reads the `idx` field from the used ring.
201
+ ///
202
+ /// # Arguments
203
+ /// * `order` - the memory ordering used to access the `idx` field from memory.
204
+ pub fn used_idx ( & self , order : Ordering ) -> Result < Wrapping < u16 > , Error > {
205
+ self . state . used_idx ( self . mem . memory ( ) . deref ( ) , order)
206
+ }
207
+
200
208
/// Put a used descriptor head into the used ring.
201
209
///
202
210
/// # Arguments
@@ -236,13 +244,26 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
236
244
self . state . next_avail ( )
237
245
}
238
246
247
+ /// Returns the index for the next descriptor in the used ring.
248
+ pub fn next_used ( & self ) -> u16 {
249
+ self . state . next_used ( )
250
+ }
251
+
239
252
/// Set the index of the next entry in the available ring.
240
253
///
241
254
/// # Arguments
242
255
/// * `next_avail` - the index of the next available ring entry.
243
256
pub fn set_next_avail ( & mut self , next_avail : u16 ) {
244
257
self . state . set_next_avail ( next_avail) ;
245
258
}
259
+
260
+ /// Sets the index for the next descriptor in the used ring.
261
+ ///
262
+ /// # Arguments
263
+ /// * `next_used` - the index of the next used ring entry.
264
+ pub fn set_next_used ( & mut self , next_used : u16 ) {
265
+ self . state . set_next_used ( next_used) ;
266
+ }
246
267
}
247
268
248
269
impl < M : GuestAddressSpace > Queue < M , QueueState > {
@@ -348,6 +369,7 @@ mod tests {
348
369
let vq = MockSplitQueue :: new ( m, 16 ) ;
349
370
let mut q = vq. create_queue ( m) ;
350
371
372
+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 0 ) ) ;
351
373
assert_eq ! ( u16 :: from_le( vq. used( ) . idx( ) . load( ) ) , 0 ) ;
352
374
353
375
// index too large
@@ -357,6 +379,7 @@ mod tests {
357
379
// should be ok
358
380
q. add_used ( 1 , 0x1000 ) . unwrap ( ) ;
359
381
assert_eq ! ( q. state. next_used, Wrapping ( 1 ) ) ;
382
+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 1 ) ) ;
360
383
assert_eq ! ( u16 :: from_le( vq. used( ) . idx( ) . load( ) ) , 1 ) ;
361
384
362
385
let x = vq. used ( ) . ring ( ) . ref_at ( 0 ) . load ( ) ;
@@ -377,7 +400,7 @@ mod tests {
377
400
// Same for `event_idx_enabled`, `next_avail` `next_used` and `signalled_used`.
378
401
q. set_event_idx ( true ) ;
379
402
q. set_next_avail ( 2 ) ;
380
- q. add_used ( 1 , 200 ) . unwrap ( ) ;
403
+ q. set_next_used ( 4 ) ;
381
404
q. state . signalled_used = Some ( Wrapping ( 15 ) ) ;
382
405
assert_eq ! ( q. state. size, 8 ) ;
383
406
// `create_queue` also marks the queue as ready.
@@ -533,10 +556,14 @@ mod tests {
533
556
i += 1 ;
534
557
q. disable_notification ( ) . unwrap ( ) ;
535
558
536
- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
559
+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
537
560
// Here the device would consume entries from the available ring, add an entry in
538
561
// the used ring and optionally notify the driver. For the purpose of this test, we
539
562
// don't need to do anything with the chain, only consume it.
563
+ let head_index = chain. head_index ( ) ;
564
+ let mut desc_len = 0 ;
565
+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
566
+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
540
567
}
541
568
if !q. enable_notification ( ) . unwrap ( ) {
542
569
break ;
@@ -547,6 +574,7 @@ mod tests {
547
574
assert_eq ! ( i, 1 ) ;
548
575
// The next chain that can be consumed should have index 2.
549
576
assert_eq ! ( q. next_avail( ) , 2 ) ;
577
+ assert_eq ! ( q. next_used( ) , 2 ) ;
550
578
// Let the device know it can consume one more chain.
551
579
vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 3 ) ) ;
552
580
i = 0 ;
@@ -555,8 +583,12 @@ mod tests {
555
583
i += 1 ;
556
584
q. disable_notification ( ) . unwrap ( ) ;
557
585
558
- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
586
+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
559
587
// In a real use case, we would do something with the chain here.
588
+ let head_index = chain. head_index ( ) ;
589
+ let mut desc_len = 0 ;
590
+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
591
+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
560
592
}
561
593
562
594
// For the simplicity of the test we are updating here the `idx` value of the available
@@ -571,21 +603,27 @@ mod tests {
571
603
assert_eq ! ( i, 2 ) ;
572
604
// The next chain that can be consumed should have index 4.
573
605
assert_eq ! ( q. next_avail( ) , 4 ) ;
606
+ assert_eq ! ( q. next_used( ) , 4 ) ;
574
607
575
608
// Set an `idx` that is bigger than the number of entries added in the ring.
576
609
// This is an allowed scenario, but the indexes of the chain will have unexpected values.
577
610
vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 7 ) ) ;
578
611
loop {
579
612
q. disable_notification ( ) . unwrap ( ) ;
580
613
581
- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
614
+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
582
615
// In a real use case, we would do something with the chain here.
616
+ let head_index = chain. head_index ( ) ;
617
+ let mut desc_len = 0 ;
618
+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
619
+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
583
620
}
584
621
if !q. enable_notification ( ) . unwrap ( ) {
585
622
break ;
586
623
}
587
624
}
588
625
assert_eq ! ( q. next_avail( ) , 7 ) ;
626
+ assert_eq ! ( q. next_used( ) , 7 ) ;
589
627
}
590
628
591
629
#[ test]
@@ -619,14 +657,19 @@ mod tests {
619
657
vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 3 ) ) ;
620
658
// No descriptor chains are consumed at this point.
621
659
assert_eq ! ( q. next_avail( ) , 0 ) ;
660
+ assert_eq ! ( q. next_used( ) , 0 ) ;
622
661
623
662
loop {
624
663
q. disable_notification ( ) . unwrap ( ) ;
625
664
626
- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
665
+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
627
666
// Here the device would consume entries from the available ring, add an entry in
628
667
// the used ring and optionally notify the driver. For the purpose of this test, we
629
668
// don't need to do anything with the chain, only consume it.
669
+ let head_index = chain. head_index ( ) ;
670
+ let mut desc_len = 0 ;
671
+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
672
+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
630
673
}
631
674
if !q. enable_notification ( ) . unwrap ( ) {
632
675
break ;
@@ -635,6 +678,8 @@ mod tests {
635
678
// The next chain that can be consumed should have index 3.
636
679
assert_eq ! ( q. next_avail( ) , 3 ) ;
637
680
assert_eq ! ( q. avail_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 3 ) ) ;
681
+ assert_eq ! ( q. next_used( ) , 3 ) ;
682
+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 3 ) ) ;
638
683
assert ! ( q. lock( ) . ready( ) ) ;
639
684
640
685
// Decrement `idx` which should be forbidden. We don't enforce this thing, but we should
0 commit comments