From 340a3f82dd09b5bd65b545797e276948b5e56f53 Mon Sep 17 00:00:00 2001 From: Erik Schilling Date: Thu, 28 Sep 2023 12:03:21 +0200 Subject: [PATCH] gpio: guard libgpiod::Chip with Mutex The Chip is not `Sync` (as wrongly claimed by the `Sync` marker on `PhysDevice`). So if we want to share the `PhysDevice` across threads, we will need to guard it by a `Mutex`. These calls do not block for very long. So this should not cause any new deadlock conditions. Issue: #442 Signed-off-by: Erik Schilling --- crates/vhost-device-gpio/src/gpio.rs | 35 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/crates/vhost-device-gpio/src/gpio.rs b/crates/vhost-device-gpio/src/gpio.rs index ae29003..7dbc6a6 100644 --- a/crates/vhost-device-gpio/src/gpio.rs +++ b/crates/vhost-device-gpio/src/gpio.rs @@ -91,7 +91,7 @@ pub(crate) struct PhysLineState { } pub(crate) struct PhysDevice { - chip: chip::Chip, + chip: Mutex, ngpio: u16, state: Vec>, } @@ -121,7 +121,11 @@ impl GpioDevice for PhysDevice { }) }); - Ok(PhysDevice { chip, ngpio, state }) + Ok(PhysDevice { + chip: Mutex::new(chip), + ngpio, + state, + }) } fn num_gpios(&self) -> Result { @@ -131,6 +135,8 @@ impl GpioDevice for PhysDevice { fn gpio_name(&self, gpio: u16) -> Result { let line_info = self .chip + .lock() + .unwrap() .line_info(gpio.into()) .map_err(Error::GpiodFailed)?; @@ -140,6 +146,8 @@ impl GpioDevice for PhysDevice { fn direction(&self, gpio: u16) -> Result { let line_info = self .chip + .lock() + .unwrap() .line_info(gpio.into()) .map_err(Error::GpiodFailed)?; @@ -195,22 +203,13 @@ impl GpioDevice for PhysDevice { .set_consumer("vhu-gpio") .map_err(Error::GpiodFailed)?; - // This is causing a warning since libgpiod's request_config is - // not `Send`. - // We, however, unsafely claim that it is by marking PhysDevice as - // `Send`. This is wrong, but until we figure out what to do, we - // just silence the clippy warning here. - // - // https://github.com/rust-vmm/vhost-device/issues/442 tracks - // finding a solution to this. - #[allow(clippy::arc_with_non_send_sync)] - { - state.request = Some(Arc::new(Mutex::new( - self.chip - .request_lines(Some(&rconfig), &lconfig) - .map_err(Error::GpiodFailed)?, - ))); - } + state.request = Some( + self.chip + .lock() + .unwrap() + .request_lines(Some(&rconfig), &lconfig) + .map_err(Error::GpiodFailed)?, + ); } Ok(())