Skip to content

Commit e252a24

Browse files
committed
queue: add QueueStateSync for multi-threading
Introduce QueueStateSync, which is essentially Arc<Mutex<QueueState>>, for multi-threaded context. The QueueStateSync object could be cloned and sent to different threads for concurrently processing available descriptors. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
1 parent ca901e9 commit e252a24

File tree

1 file changed

+93
-2
lines changed

1 file changed

+93
-2
lines changed

crates/virtio-queue/src/lib.rs

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
// Copyright © 2019 Intel Corporation
88
//
9-
// Copyright (C) 2020 Alibaba Cloud. All rights reserved.
9+
// Copyright (C) 2020-2021 Alibaba Cloud. All rights reserved.
1010
//
1111
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
1212

@@ -26,7 +26,7 @@ use std::mem::size_of;
2626
use std::num::Wrapping;
2727
use std::ops::{Deref, DerefMut};
2828
use std::sync::atomic::{fence, Ordering};
29-
use std::sync::MutexGuard;
29+
use std::sync::{Arc, Mutex, MutexGuard};
3030

3131
use defs::{
3232
VIRTQ_AVAIL_ELEMENT_SIZE, VIRTQ_AVAIL_RING_HEADER_SIZE, VIRTQ_AVAIL_RING_META_SIZE,
@@ -849,6 +849,97 @@ impl<M: GuestAddressSpace> QueueStateT<M> for QueueState<M> {
849849
}
850850
}
851851

852+
/// Struct to maintain information and manipulate state of a virtio queue for multi-threaded
853+
/// context.
854+
#[derive(Clone, Debug)]
855+
pub struct QueueStateSync<M: GuestAddressSpace> {
856+
state: Arc<Mutex<QueueState<M>>>,
857+
}
858+
859+
impl<M: GuestAddressSpace> QueueStateT<M> for QueueStateSync<M> {
860+
fn new(max_size: u16) -> Self {
861+
QueueStateSync {
862+
state: Arc::new(Mutex::new(QueueState::new(max_size))),
863+
}
864+
}
865+
866+
fn lock(&mut self) -> QueueStateGuard<'_, M> {
867+
QueueStateGuard::MutexGuard(self.state.lock().unwrap())
868+
}
869+
870+
fn max_size(&self) -> u16 {
871+
self.state.lock().unwrap().max_size()
872+
}
873+
874+
fn actual_size(&self) -> u16 {
875+
self.state.lock().unwrap().actual_size()
876+
}
877+
878+
fn set_size(&mut self, size: u16) {
879+
self.state.lock().unwrap().set_size(size)
880+
}
881+
882+
fn ready(&self) -> bool {
883+
self.state.lock().unwrap().ready
884+
}
885+
886+
fn set_ready(&mut self, ready: bool) {
887+
self.state.lock().unwrap().set_ready(ready)
888+
}
889+
890+
fn set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>) {
891+
self.state.lock().unwrap().set_desc_table_address(low, high);
892+
}
893+
894+
fn set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
895+
self.state.lock().unwrap().set_avail_ring_address(low, high);
896+
}
897+
898+
fn set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
899+
self.state.lock().unwrap().set_used_ring_address(low, high);
900+
}
901+
902+
fn reset(&mut self) {
903+
self.state.lock().unwrap().reset();
904+
}
905+
906+
fn set_event_idx(&mut self, enabled: bool) {
907+
self.state.lock().unwrap().set_event_idx(enabled);
908+
}
909+
910+
fn is_valid(&self, mem: &M::T) -> bool {
911+
self.state.lock().unwrap().is_valid(mem)
912+
}
913+
914+
fn avail_idx(&self, mem: &M::T, order: Ordering) -> Result<Wrapping<u16>, Error> {
915+
self.state.lock().unwrap().avail_idx(mem, order)
916+
}
917+
918+
fn add_used(&mut self, mem: &M::T, head_index: u16, len: u32) -> Result<(), Error> {
919+
self.state.lock().unwrap().add_used(mem, head_index, len)
920+
}
921+
922+
fn enable_notification(&mut self, mem: &M::T) -> Result<bool, Error> {
923+
self.state.lock().unwrap().enable_notification(mem)
924+
}
925+
926+
fn disable_notification(&mut self, mem: &M::T) -> Result<(), Error> {
927+
self.state.lock().unwrap().disable_notification(mem)
928+
}
929+
930+
fn needs_notification(&mut self, mem: &M::T) -> Result<bool, Error> {
931+
self.state.lock().unwrap().needs_notification(mem)
932+
}
933+
934+
fn next_avail(&self) -> u16 {
935+
self.state.lock().unwrap().next_avail()
936+
}
937+
938+
fn set_next_avail(&mut self, next_avail: u16) {
939+
self.state.lock().unwrap().set_next_avail(next_avail);
940+
}
941+
}
942+
852943
/// A convenient wrapper struct for a virtio queue, with associated GuestMemory object.
853944
#[derive(Clone, Debug)]
854945
pub struct Queue<M: GuestAddressSpace, S: QueueStateT<M> = QueueState<M>> {

0 commit comments

Comments
 (0)