Skip to content

Commit 205a75e

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 0462b37 commit 205a75e

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,
@@ -872,6 +872,97 @@ impl<M: GuestAddressSpace> QueueStateT<M> for QueueState<M> {
872872
}
873873
}
874874

875+
/// Struct to maintain information and manipulate state of a virtio queue for multi-threaded
876+
/// context.
877+
#[derive(Clone, Debug)]
878+
pub struct QueueStateSync<M: GuestAddressSpace> {
879+
state: Arc<Mutex<QueueState<M>>>,
880+
}
881+
882+
impl<M: GuestAddressSpace> QueueStateT<M> for QueueStateSync<M> {
883+
fn new(max_size: u16) -> Self {
884+
QueueStateSync {
885+
state: Arc::new(Mutex::new(QueueState::new(max_size))),
886+
}
887+
}
888+
889+
fn is_valid(&self, mem: &M::T) -> bool {
890+
self.state.lock().unwrap().is_valid(mem)
891+
}
892+
893+
fn reset(&mut self) {
894+
self.state.lock().unwrap().reset();
895+
}
896+
897+
fn lock(&mut self) -> QueueStateGuard<'_, M> {
898+
QueueStateGuard::MutexGuard(self.state.lock().unwrap())
899+
}
900+
901+
fn max_size(&self) -> u16 {
902+
self.state.lock().unwrap().max_size()
903+
}
904+
905+
fn actual_size(&self) -> u16 {
906+
self.state.lock().unwrap().actual_size()
907+
}
908+
909+
fn set_size(&mut self, size: u16) {
910+
self.state.lock().unwrap().set_size(size)
911+
}
912+
913+
fn ready(&self) -> bool {
914+
self.state.lock().unwrap().ready
915+
}
916+
917+
fn set_ready(&mut self, ready: bool) {
918+
self.state.lock().unwrap().set_ready(ready)
919+
}
920+
921+
fn set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>) {
922+
self.state.lock().unwrap().set_desc_table_address(low, high);
923+
}
924+
925+
fn set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
926+
self.state.lock().unwrap().set_avail_ring_address(low, high);
927+
}
928+
929+
fn set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
930+
self.state.lock().unwrap().set_used_ring_address(low, high);
931+
}
932+
933+
fn set_event_idx(&mut self, enabled: bool) {
934+
self.state.lock().unwrap().set_event_idx(enabled);
935+
}
936+
937+
fn avail_idx(&self, mem: &M::T, order: Ordering) -> Result<Wrapping<u16>, Error> {
938+
self.state.lock().unwrap().avail_idx(mem, order)
939+
}
940+
941+
fn add_used(&mut self, mem: &M::T, head_index: u16, len: u32) -> Result<(), Error> {
942+
self.state.lock().unwrap().add_used(mem, head_index, len)
943+
}
944+
945+
fn enable_notification(&mut self, mem: &M::T) -> Result<bool, Error> {
946+
self.state.lock().unwrap().enable_notification(mem)
947+
}
948+
949+
fn disable_notification(&mut self, mem: &M::T) -> Result<(), Error> {
950+
self.state.lock().unwrap().disable_notification(mem)
951+
}
952+
953+
fn needs_notification(&mut self, mem: &M::T) -> Result<bool, Error> {
954+
self.state.lock().unwrap().needs_notification(mem)
955+
}
956+
957+
fn next_avail(&self) -> u16 {
958+
self.state.lock().unwrap().next_avail()
959+
}
960+
961+
fn set_next_avail(&mut self, next_avail: u16) {
962+
self.state.lock().unwrap().set_next_avail(next_avail);
963+
}
964+
}
965+
875966
/// A convenient wrapper struct for a virtio queue, with associated GuestMemory object.
876967
#[derive(Clone, Debug)]
877968
pub struct Queue<M: GuestAddressSpace, S: QueueStateT<M> = QueueState<M>> {

0 commit comments

Comments
 (0)