devices: Make Bus hold a list of Weak BusDevice references

By storing a list of Weak references to BusDevice devices, the Bus
structure prevents potential cyclic dependencies from happening on
strong references.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-03-04 16:04:32 +01:00
parent 7773812f58
commit ca426cfdf4

View File

@ -9,7 +9,7 @@
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
use std::collections::btree_map::BTreeMap; use std::collections::btree_map::BTreeMap;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock, Weak};
use std::{convert, error, fmt, io, result}; use std::{convert, error, fmt, io, result};
/// Trait for devices that respond to reads or writes in an arbitrary address space. /// Trait for devices that respond to reads or writes in an arbitrary address space.
@ -95,7 +95,7 @@ impl PartialOrd for BusRange {
/// only restriction is that no two devices can overlap in this address space. /// only restriction is that no two devices can overlap in this address space.
#[derive(Default)] #[derive(Default)]
pub struct Bus { pub struct Bus {
devices: RwLock<BTreeMap<BusRange, Arc<Mutex<dyn BusDevice>>>>, devices: RwLock<BTreeMap<BusRange, Weak<Mutex<dyn BusDevice>>>>,
} }
impl Bus { impl Bus {
@ -112,7 +112,7 @@ impl Bus {
.range(..=BusRange { base: addr, len: 1 }) .range(..=BusRange { base: addr, len: 1 })
.rev() .rev()
.next()?; .next()?;
Some((*range, dev.clone())) Some((*range, dev.upgrade().unwrap().clone()))
} }
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
@ -147,7 +147,7 @@ impl Bus {
.devices .devices
.write() .write()
.unwrap() .unwrap()
.insert(BusRange { base, len }, device) .insert(BusRange { base, len }, Arc::downgrade(&device))
.is_some() .is_some()
{ {
return Err(Error::Overlap); return Err(Error::Overlap);
@ -312,9 +312,8 @@ mod tests {
let bus = Bus::new(); let bus = Bus::new();
let mut data = [1, 2, 3, 4]; let mut data = [1, 2, 3, 4];
assert!(bus let device = Arc::new(Mutex::new(DummyDevice));
.insert(Arc::new(Mutex::new(DummyDevice)), 0x10, 0x10) assert!(bus.insert(device.clone(), 0x10, 0x10).is_ok());
.is_ok());
assert!(bus.write(0x10, &mut data)); assert!(bus.write(0x10, &mut data));
assert!(bus.read(0x10, &mut data)); assert!(bus.read(0x10, &mut data));
assert_eq!(data, [1, 2, 3, 4]); assert_eq!(data, [1, 2, 3, 4]);