@@ -29,6 +29,7 @@ use std::mem::size_of;
2929use std:: num:: Wrapping ;
3030use std:: ops:: { Deref , DerefMut } ;
3131use std:: sync:: atomic:: { fence, Ordering } ;
32+ use std:: sync:: { Arc , Mutex , MutexGuard } ;
3233
3334use log:: error;
3435use vm_memory:: {
@@ -1028,9 +1029,37 @@ impl<M: GuestAddressSpace> Queue<M> {
10281029 }
10291030}
10301031
1032+ /// A convenient wrapper struct for a thread-safe virtio queue, with associated GuestMemory object.
1033+ #[ derive( Clone , Debug ) ]
1034+ pub struct QueueSync < M : GuestAddressSpace > {
1035+ /// Guest memory object associated with the queue.
1036+ pub mem : M ,
1037+ /// Virtio queue state.
1038+ pub state : Arc < Mutex < QueueState > > ,
1039+ }
1040+
1041+ impl < M : GuestAddressSpace > QueueSync < M > {
1042+ /// Construct an empty virtio queue with the given `max_size`.
1043+ pub fn new ( mem : M , max_size : u16 ) -> Self {
1044+ QueueSync {
1045+ mem,
1046+ state : Arc :: new ( Mutex :: new ( QueueState :: new ( max_size) ) ) ,
1047+ }
1048+ }
1049+
1050+ /// Get an exclusive reference to the underlying `QueueState` object.
1051+ ///
1052+ /// Logically this method will acquire the underlying lock protecting the `QueueState`
1053+ /// object. The lock will be released when the returned object gets dropped.
1054+ pub fn lock ( & self ) -> QueueGuard < M :: T , MutexGuard < QueueState > > {
1055+ QueueGuard :: new ( self . mem . memory ( ) , self . state . lock ( ) . unwrap ( ) )
1056+ }
1057+ }
1058+
10311059#[ cfg( test) ]
10321060mod tests {
10331061 use super :: * ;
1062+ use generic:: QueueT ;
10341063 use memoffset:: offset_of;
10351064 use mock:: { DescriptorTable , MockSplitQueue } ;
10361065
@@ -1193,72 +1222,74 @@ mod tests {
11931222 assert ! ( q. is_valid( ) ) ;
11941223
11951224 // shouldn't be valid when not marked as ready
1196- q. state . ready = false ;
1225+ q. with ( | mut qstate| qstate . ready = false ) ;
11971226 assert ! ( !q. is_valid( ) ) ;
1198- q. state . ready = true ;
1227+ q. with ( |mut qstate| qstate. ready = true ) ;
1228+
1229+ let max_size = q. with ( |qstate| qstate. max_size ) ;
11991230
12001231 // or when size > max_size
1201- q. state . size = q . state . max_size << 1 ;
1232+ q. with ( | mut qstate| qstate . size = max_size << 1 ) ;
12021233 assert ! ( !q. is_valid( ) ) ;
1203- q. state . size = q . state . max_size ;
1234+ q. with ( | mut qstate| qstate . size = max_size) ;
12041235
12051236 // or when size is 0
1206- q. state . size = 0 ;
1237+ q. with ( | mut qstate| qstate . size = 0 ) ;
12071238 assert ! ( !q. is_valid( ) ) ;
1208- q. state . size = q . state . max_size ;
1239+ q. with ( | mut qstate| qstate . size = max_size) ;
12091240
12101241 // or when size is not a power of 2
1211- q. state . size = 11 ;
1242+ q. with ( | mut qstate| qstate . size = 11 ) ;
12121243 assert ! ( !q. is_valid( ) ) ;
1213- q. state . size = q . state . max_size ;
1244+ q. with ( | mut qstate| qstate . size = max_size) ;
12141245
12151246 // or if the various addresses are off
12161247
1217- q. state . desc_table = GuestAddress ( 0xffff_ffff ) ;
1248+ q. with ( | mut qstate| qstate . desc_table = GuestAddress ( 0xffff_ffff ) ) ;
12181249 assert ! ( !q. is_valid( ) ) ;
1219- q. state . desc_table = GuestAddress ( 0x1001 ) ;
1250+ q. with ( | mut qstate| qstate . desc_table = GuestAddress ( 0x1001 ) ) ;
12201251 assert ! ( !q. is_valid( ) ) ;
1221- q. state . desc_table = vq. desc_table_addr ( ) ;
1252+ q. with ( | mut qstate| qstate . desc_table = vq. desc_table_addr ( ) ) ;
12221253
1223- q. state . avail_ring = GuestAddress ( 0xffff_ffff ) ;
1254+ q. with ( | mut qstate| qstate . avail_ring = GuestAddress ( 0xffff_ffff ) ) ;
12241255 assert ! ( !q. is_valid( ) ) ;
1225- q. state . avail_ring = GuestAddress ( 0x1001 ) ;
1256+ q. with ( | mut qstate| qstate . avail_ring = GuestAddress ( 0x1001 ) ) ;
12261257 assert ! ( !q. is_valid( ) ) ;
1227- q. state . avail_ring = vq. avail_addr ( ) ;
1258+ q. with ( | mut qstate| qstate . avail_ring = vq. avail_addr ( ) ) ;
12281259
1229- q. state . used_ring = GuestAddress ( 0xffff_ffff ) ;
1260+ q. with ( | mut qstate| qstate . used_ring = GuestAddress ( 0xffff_ffff ) ) ;
12301261 assert ! ( !q. is_valid( ) ) ;
1231- q. state . used_ring = GuestAddress ( 0x1001 ) ;
1262+ q. with ( | mut qstate| qstate . used_ring = GuestAddress ( 0x1001 ) ) ;
12321263 assert ! ( !q. is_valid( ) ) ;
1233- q. state . used_ring = vq. used_addr ( ) ;
1264+ q. with ( | mut qstate| qstate . used_ring = vq. used_addr ( ) ) ;
12341265
1235- {
1266+ q . with ( | mut qstate| {
12361267 // an invalid queue should return an iterator with no next
1237- q . state . ready = false ;
1238- let mut i = q . iter ( ) . unwrap ( ) ;
1268+ qstate . ready = false ;
1269+ let mut i = qstate . iter ( ) . unwrap ( ) ;
12391270 assert ! ( i. next( ) . is_none( ) ) ;
1240- }
1271+ } ) ;
12411272
1242- q. state . ready = true ;
1273+ q. with ( | mut qstate| qstate . ready = true ) ;
12431274
12441275 // now let's create two simple descriptor chains
12451276 // the chains are (0, 1) and (2, 3, 4)
1246- {
1247- for j in 0 ..5u16 {
1248- let flags = match j {
1249- 1 | 4 => 0 ,
1250- _ => VIRTQ_DESC_F_NEXT ,
1251- } ;
1252-
1253- let desc = Descriptor :: new ( ( 0x1000 * ( j + 1 ) ) as u64 , 0x1000 , flags, j + 1 ) ;
1254- vq. desc_table ( ) . store ( j, desc) ;
1255- }
1277+ for j in 0 ..5u16 {
1278+ let flags = match j {
1279+ 1 | 4 => 0 ,
1280+ _ => VIRTQ_DESC_F_NEXT ,
1281+ } ;
12561282
1257- vq. avail ( ) . ring ( ) . ref_at ( 0 ) . store ( 0 ) ;
1258- vq. avail ( ) . ring ( ) . ref_at ( 1 ) . store ( 2 ) ;
1259- vq. avail ( ) . idx ( ) . store ( 2 ) ;
1283+ let desc = Descriptor :: new ( ( 0x1000 * ( j + 1 ) ) as u64 , 0x1000 , flags, j + 1 ) ;
1284+ vq. desc_table ( ) . store ( j, desc) ;
1285+ }
1286+
1287+ vq. avail ( ) . ring ( ) . ref_at ( 0 ) . store ( 0 ) ;
1288+ vq. avail ( ) . ring ( ) . ref_at ( 1 ) . store ( 2 ) ;
1289+ vq. avail ( ) . idx ( ) . store ( 2 ) ;
12601290
1261- let mut i = q. iter ( ) . unwrap ( ) ;
1291+ q. with ( |mut qstate| {
1292+ let mut i = qstate. iter ( ) . unwrap ( ) ;
12621293
12631294 {
12641295 let mut c = i. next ( ) . unwrap ( ) ;
@@ -1285,13 +1316,13 @@ mod tests {
12851316 {
12861317 assert ! ( i. next( ) . is_none( ) ) ;
12871318 i. go_to_previous_position ( ) ;
1288- let mut c = q . iter ( ) . unwrap ( ) . next ( ) . unwrap ( ) ;
1319+ let mut c = qstate . iter ( ) . unwrap ( ) . next ( ) . unwrap ( ) ;
12891320 c. next ( ) . unwrap ( ) ;
12901321 c. next ( ) . unwrap ( ) ;
12911322 c. next ( ) . unwrap ( ) ;
12921323 assert ! ( c. next( ) . is_none( ) ) ;
12931324 }
1294- }
1325+ } )
12951326 }
12961327
12971328 #[ test]
@@ -1321,39 +1352,41 @@ mod tests {
13211352 vq. avail ( ) . ring ( ) . ref_at ( 2 ) . store ( 5 ) ;
13221353 vq. avail ( ) . idx ( ) . store ( 3 ) ;
13231354
1324- let mut i = q. iter ( ) . unwrap ( ) ;
1355+ q. with ( |mut qstate| {
1356+ let mut i = qstate. iter ( ) . unwrap ( ) ;
13251357
1326- {
1327- let c = i. next ( ) . unwrap ( ) ;
1328- assert_eq ! ( c. head_index( ) , 0 ) ;
1329-
1330- let mut iter = c;
1331- assert ! ( iter. next( ) . is_some( ) ) ;
1332- assert ! ( iter. next( ) . is_some( ) ) ;
1333- assert ! ( iter. next( ) . is_none( ) ) ;
1334- assert ! ( iter. next( ) . is_none( ) ) ;
1335- }
1358+ {
1359+ let c = i. next ( ) . unwrap ( ) ;
1360+ assert_eq ! ( c. head_index( ) , 0 ) ;
13361361
1337- {
1338- let c = i. next ( ) . unwrap ( ) ;
1339- assert_eq ! ( c. head_index( ) , 2 ) ;
1340-
1341- let mut iter = c. writable ( ) ;
1342- assert ! ( iter. next( ) . is_some( ) ) ;
1343- assert ! ( iter. next( ) . is_some( ) ) ;
1344- assert ! ( iter. next( ) . is_none( ) ) ;
1345- assert ! ( iter. next( ) . is_none( ) ) ;
1346- }
1362+ let mut iter = c;
1363+ assert ! ( iter. next( ) . is_some( ) ) ;
1364+ assert ! ( iter. next( ) . is_some( ) ) ;
1365+ assert ! ( iter. next( ) . is_none( ) ) ;
1366+ assert ! ( iter. next( ) . is_none( ) ) ;
1367+ }
13471368
1348- {
1349- let c = i. next ( ) . unwrap ( ) ;
1350- assert_eq ! ( c. head_index( ) , 5 ) ;
1369+ {
1370+ let c = i. next ( ) . unwrap ( ) ;
1371+ assert_eq ! ( c. head_index( ) , 2 ) ;
13511372
1352- let mut iter = c. readable ( ) ;
1353- assert ! ( iter. next( ) . is_some( ) ) ;
1354- assert ! ( iter. next( ) . is_none( ) ) ;
1355- assert ! ( iter. next( ) . is_none( ) ) ;
1356- }
1373+ let mut iter = c. writable ( ) ;
1374+ assert ! ( iter. next( ) . is_some( ) ) ;
1375+ assert ! ( iter. next( ) . is_some( ) ) ;
1376+ assert ! ( iter. next( ) . is_none( ) ) ;
1377+ assert ! ( iter. next( ) . is_none( ) ) ;
1378+ }
1379+
1380+ {
1381+ let c = i. next ( ) . unwrap ( ) ;
1382+ assert_eq ! ( c. head_index( ) , 5 ) ;
1383+
1384+ let mut iter = c. readable ( ) ;
1385+ assert ! ( iter. next( ) . is_some( ) ) ;
1386+ assert ! ( iter. next( ) . is_none( ) ) ;
1387+ assert ! ( iter. next( ) . is_none( ) ) ;
1388+ }
1389+ } )
13571390 }
13581391
13591392 #[ test]
@@ -1371,7 +1404,7 @@ mod tests {
13711404
13721405 // should be ok
13731406 q. add_used ( 1 , 0x1000 ) . unwrap ( ) ;
1374- assert_eq ! ( q . state . next_used, Wrapping ( 1 ) ) ;
1407+ q . with ( |qstate| assert_eq ! ( qstate . next_used, Wrapping ( 1 ) ) ) ;
13751408 assert_eq ! ( vq. used( ) . idx( ) . load( ) , 1 ) ;
13761409
13771410 let x = vq. used ( ) . ring ( ) . ref_at ( 0 ) . load ( ) ;
@@ -1399,11 +1432,13 @@ mod tests {
13991432 let vq = MockSplitQueue :: new ( m, 16 ) ;
14001433
14011434 let mut q: Queue < _ > = vq. as_queue ( m) ;
1402- q. state . size = 8 ;
1403- q. state . ready = true ;
1404- q. state . reset ( ) ;
1405- assert_eq ! ( q. state. size, 16 ) ;
1406- assert_eq ! ( q. state. ready, false ) ;
1435+ q. with ( |mut qstate| {
1436+ qstate. size = 8 ;
1437+ qstate. ready = true ;
1438+ qstate. reset ( ) ;
1439+ assert_eq ! ( qstate. size, 16 ) ;
1440+ assert_eq ! ( qstate. ready, false ) ;
1441+ } )
14071442 }
14081443
14091444 #[ test]
@@ -1417,21 +1452,24 @@ mod tests {
14171452
14181453 // It should always return true when EVENT_IDX isn't enabled.
14191454 for i in 0 ..qsize {
1420- q. state . next_used = Wrapping ( i) ;
1455+ q. with ( | mut qstate| qstate . next_used = Wrapping ( i) ) ;
14211456 assert_eq ! ( q. needs_notification( ) . unwrap( ) , true ) ;
14221457 }
14231458
14241459 m. write_obj :: < u16 > ( 4 , avail_addr. unchecked_add ( 4 + qsize as u64 * 2 ) )
14251460 . unwrap ( ) ;
1426- q. state . set_event_idx ( true ) ;
1461+ q. with ( | mut qstate| qstate . set_event_idx ( true ) ) ;
14271462
14281463 // Incrementing up to this value causes an `u16` to wrap back to 0.
14291464 let wrap = u32:: from ( u16:: MAX ) + 1 ;
14301465
14311466 for i in 0 ..wrap + 12 {
1432- q. state . next_used = Wrapping ( i as u16 ) ;
1433- // Let's test wrapping around the maximum index value as well.
1434- let expected = i == 5 || i == ( 5 + wrap) || q. state . signalled_used . is_none ( ) ;
1467+ let expected = q. with ( |mut qstate| {
1468+ qstate. next_used = Wrapping ( i as u16 ) ;
1469+ // Let's test wrapping around the maximum index value as well.
1470+ i == 5 || i == ( 5 + wrap) || qstate. signalled_used . is_none ( )
1471+ } ) ;
1472+
14351473 assert_eq ! ( q. needs_notification( ) . unwrap( ) , expected) ;
14361474 }
14371475
@@ -1445,9 +1483,9 @@ mod tests {
14451483 . unwrap ( ) ;
14461484
14471485 assert_eq ! ( q. needs_notification( ) . unwrap( ) , false ) ;
1448- q. state . next_used = Wrapping ( 15 ) ;
1486+ q. with ( | mut qstate| qstate . next_used = Wrapping ( 15 ) ) ;
14491487 assert_eq ! ( q. needs_notification( ) . unwrap( ) , false ) ;
1450- q. state . next_used = Wrapping ( 0 ) ;
1488+ q. with ( | mut qstate| qstate . next_used = Wrapping ( 0 ) ) ;
14511489 assert_eq ! ( q. needs_notification( ) . unwrap( ) , true ) ;
14521490 assert_eq ! ( q. needs_notification( ) . unwrap( ) , false ) ;
14531491 }
@@ -1460,7 +1498,7 @@ mod tests {
14601498 let mut q: Queue < _ > = vq. as_queue ( m) ;
14611499 let used_addr = vq. used_addr ( ) ;
14621500
1463- assert_eq ! ( q . state . event_idx_enabled, false ) ;
1501+ q . with ( |qstate| assert_eq ! ( qstate . event_idx_enabled, false ) ) ;
14641502
14651503 q. enable_notification ( ) . unwrap ( ) ;
14661504 let v = m. read_obj :: < u16 > ( used_addr) . unwrap ( ) ;
@@ -1479,13 +1517,13 @@ mod tests {
14791517 m. write_obj :: < u16 > ( 2 , avail_addr. unchecked_add ( 2 ) ) . unwrap ( ) ;
14801518
14811519 assert_eq ! ( q. enable_notification( ) . unwrap( ) , true ) ;
1482- q. state . next_avail = Wrapping ( 2 ) ;
1520+ q. with ( | mut qstate| qstate . next_avail = Wrapping ( 2 ) ) ;
14831521 assert_eq ! ( q. enable_notification( ) . unwrap( ) , false ) ;
14841522
14851523 m. write_obj :: < u16 > ( 8 , avail_addr. unchecked_add ( 2 ) ) . unwrap ( ) ;
14861524
14871525 assert_eq ! ( q. enable_notification( ) . unwrap( ) , true ) ;
1488- q. state . next_avail = Wrapping ( 8 ) ;
1526+ q. with ( | mut qstate| qstate . next_avail = Wrapping ( 8 ) ) ;
14891527 assert_eq ! ( q. enable_notification( ) . unwrap( ) , false ) ;
14901528 }
14911529}
0 commit comments