Skip to content

Commit

Permalink
Implement Send and Sync for various types.
Browse files Browse the repository at this point in the history
None of these types are bound to any particular thread, and there is no
interior mutability; they use &mut self for any methods that change
state.

Note that Send and Sync are automatically derived for some device types,
e.g. VirtIOBlk and VirtIOGpu, so we don't need explicit implementations
for them.
  • Loading branch information
qwandor committed Apr 29, 2024
1 parent 2f12110 commit 0355128
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/device/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ pub struct VirtIOConsole<H: Hal, T: Transport> {
receive_token: Option<u16>,
}

// SAFETY: The config space can be accessed from any thread.
unsafe impl<H: Hal, T: Transport + Send> Send for VirtIOConsole<H, T> where
VirtQueue<H, QUEUE_SIZE>: Send
{
}

// SAFETY: A `&VirtIOConsole` only allows reading the config space.
unsafe impl<H: Hal, T: Transport + Sync> Sync for VirtIOConsole<H, T> where
VirtQueue<H, QUEUE_SIZE>: Sync
{
}

/// Information about a console device, read from its configuration space.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ConsoleInfo {
Expand Down
12 changes: 12 additions & 0 deletions src/device/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
}
}

// SAFETY: The config space can be accessed from any thread.
unsafe impl<H: Hal, T: Transport + Send> Send for VirtIOInput<H, T> where
VirtQueue<H, QUEUE_SIZE>: Send
{
}

// SAFETY: An '&VirtIOInput` can't do anything, all methods take `&mut self`.
unsafe impl<H: Hal, T: Transport + Sync> Sync for VirtIOInput<H, T> where
VirtQueue<H, QUEUE_SIZE>: Sync
{
}

impl<H: Hal, T: Transport> Drop for VirtIOInput<H, T> {
fn drop(&mut self) {
// Clear any pointers pointing to DMA regions, so the device doesn't try to access them
Expand Down
12 changes: 12 additions & 0 deletions src/device/socket/vsock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,18 @@ pub struct VirtIOSocket<H: Hal, T: Transport> {
rx_queue_buffers: [NonNull<[u8; RX_BUFFER_SIZE]>; QUEUE_SIZE],
}

// SAFETY: The `rx_queue_buffers` can be accessed from any thread.
unsafe impl<H: Hal, T: Transport + Send> Send for VirtIOSocket<H, T> where
VirtQueue<H, QUEUE_SIZE>: Send
{
}

// SAFETY: A `&VirtIOSocket` only allows reading the guest CID from a field.
unsafe impl<H: Hal, T: Transport + Sync> Sync for VirtIOSocket<H, T> where
VirtQueue<H, QUEUE_SIZE>: Sync
{
}

impl<H: Hal, T: Transport> Drop for VirtIOSocket<H, T> {
fn drop(&mut self) {
// Clear any pointers pointing to DMA regions, so the device doesn't try to access them
Expand Down
7 changes: 7 additions & 0 deletions src/hal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ pub struct Dma<H: Hal> {
_hal: PhantomData<H>,
}

// SAFETY: DMA memory can be accessed from any thread.
unsafe impl<H: Hal> Send for Dma<H> {}

// SAFETY: `&Dma` only allows pointers and physical addresses to be returned. Any actual access to
// the memory requires unsafe code, which is responsible for avoiding data races.
unsafe impl<H: Hal> Sync for Dma<H> {}

impl<H: Hal> Dma<H> {
/// Allocates the given number of pages of physically contiguous memory to be used for DMA in
/// the given direction.
Expand Down
7 changes: 7 additions & 0 deletions src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,13 @@ impl<H: Hal, const SIZE: usize> VirtQueue<H, SIZE> {
}
}

// SAFETY: None of the virt queue resources are tied to a particular thread.
unsafe impl<H: Hal, const SIZE: usize> Send for VirtQueue<H, SIZE> {}

// SAFETY: A `&VirtQueue` only allows reading from the various pointers it contains, so there is no
// data race.
unsafe impl<H: Hal, const SIZE: usize> Sync for VirtQueue<H, SIZE> {}

/// The inner layout of a VirtQueue.
///
/// Ref: 2.6 Split Virtqueues
Expand Down
7 changes: 7 additions & 0 deletions src/transport/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,13 @@ impl MmioTransport {
}
}

// SAFETY: `header` is only used for MMIO, which can happen from any thread or CPU core.
unsafe impl Send for MmioTransport {}

// SAFETY: `&MmioTransport` only allows MMIO reads or getting the config space, both of which are
// fine to happen concurrently on different CPU cores.
unsafe impl Sync for MmioTransport {}

impl Transport for MmioTransport {
fn device_type(&self) -> DeviceType {
// Safe because self.header points to a valid VirtIO MMIO region.
Expand Down
13 changes: 13 additions & 0 deletions src/transport/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,13 @@ impl Transport for PciTransport {
}
}

// SAFETY: MMIO can be done from any thread or CPU core.
unsafe impl Send for PciTransport {}

// SAFETY: `&PciTransport` only allows MMIO reads or getting the config space, both of which are
// fine to happen concurrently on different CPU cores.
unsafe impl Sync for PciTransport {}

impl Drop for PciTransport {
fn drop(&mut self) {
// Reset the device when the transport is dropped.
Expand Down Expand Up @@ -499,6 +506,12 @@ impl From<PciError> for VirtioPciError {
}
}

// SAFETY: The `vaddr` field of `VirtioPciError::Misaligned` is only used for debug output.
unsafe impl Send for VirtioPciError {}

// SAFETY: The `vaddr` field of `VirtioPciError::Misaligned` is only used for debug output.
unsafe impl Sync for VirtioPciError {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
7 changes: 7 additions & 0 deletions src/transport/pci/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ impl PciRoot {
}
}

// SAFETY: `mmio_base` is only used for MMIO, which can happen from any thread or CPU core.
unsafe impl Send for PciRoot {}

// SAFETY: `&PciRoot` only allows MMIO reads, which are fine to happen concurrently on different CPU
// cores.
unsafe impl Sync for PciRoot {}

/// Information about a PCI Base Address Register.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum BarInfo {
Expand Down

0 comments on commit 0355128

Please sign in to comment.