1extern crate arc_swap;
13
14use arc_swap::{ArcSwap, Guard};
15use std::ops::Deref;
16use std::sync::{Arc, LockResult, Mutex, MutexGuard, PoisonError};
17
18use crate::{GuestAddressSpace, GuestMemory};
19
20#[derive(Clone, Debug)]
28pub struct GuestMemoryAtomic<M: GuestMemory> {
29 inner: Arc<(ArcSwap<M>, Mutex<()>)>,
35}
36
37impl<M: GuestMemory> From<Arc<M>> for GuestMemoryAtomic<M> {
38 fn from(map: Arc<M>) -> Self {
41 let inner = (ArcSwap::new(map), Mutex::new(()));
42 GuestMemoryAtomic {
43 inner: Arc::new(inner),
44 }
45 }
46}
47
48impl<M: GuestMemory> GuestMemoryAtomic<M> {
49 pub fn new(map: M) -> Self {
52 Arc::new(map).into()
53 }
54
55 fn load(&self) -> Guard<Arc<M>> {
56 self.inner.0.load()
57 }
58
59 pub fn lock(&self) -> LockResult<GuestMemoryExclusiveGuard<M>> {
65 match self.inner.1.lock() {
66 Ok(guard) => Ok(GuestMemoryExclusiveGuard {
67 parent: self,
68 _guard: guard,
69 }),
70 Err(err) => Err(PoisonError::new(GuestMemoryExclusiveGuard {
71 parent: self,
72 _guard: err.into_inner(),
73 })),
74 }
75 }
76}
77
78impl<M: GuestMemory> GuestAddressSpace for GuestMemoryAtomic<M> {
79 type T = GuestMemoryLoadGuard<M>;
80 type M = M;
81
82 fn memory(&self) -> Self::T {
83 GuestMemoryLoadGuard { guard: self.load() }
84 }
85}
86
87#[derive(Debug)]
92pub struct GuestMemoryLoadGuard<M: GuestMemory> {
93 guard: Guard<Arc<M>>,
94}
95
96impl<M: GuestMemory> GuestMemoryLoadGuard<M> {
97 pub fn into_inner(self) -> Arc<M> {
103 Guard::into_inner(self.guard)
104 }
105}
106
107impl<M: GuestMemory> Clone for GuestMemoryLoadGuard<M> {
108 fn clone(&self) -> Self {
109 GuestMemoryLoadGuard {
110 guard: Guard::from_inner(Arc::clone(&*self.guard)),
111 }
112 }
113}
114
115impl<M: GuestMemory> Deref for GuestMemoryLoadGuard<M> {
116 type Target = M;
117
118 fn deref(&self) -> &Self::Target {
119 &self.guard
120 }
121}
122
123#[derive(Debug)]
128pub struct GuestMemoryExclusiveGuard<'a, M: GuestMemory> {
129 parent: &'a GuestMemoryAtomic<M>,
130 _guard: MutexGuard<'a, ()>,
131}
132
133impl<M: GuestMemory> GuestMemoryExclusiveGuard<'_, M> {
134 pub fn replace(self, map: M) {
138 self.parent.inner.0.store(Arc::new(map))
139 }
140}
141
142#[cfg(test)]
143#[cfg(feature = "backend-mmap")]
144mod tests {
145 use super::*;
146 use crate::{GuestAddress, GuestMemory, GuestMemoryRegion, GuestUsize, MmapRegion};
147
148 type GuestMemoryMmap = crate::GuestMemoryMmap<()>;
149 type GuestRegionMmap = crate::GuestRegionMmap<()>;
150 type GuestMemoryMmapAtomic = GuestMemoryAtomic<GuestMemoryMmap>;
151
152 #[test]
153 fn test_atomic_memory() {
154 let region_size = 0x400;
155 let regions = vec![
156 (GuestAddress(0x0), region_size),
157 (GuestAddress(0x1000), region_size),
158 ];
159 let mut iterated_regions = Vec::new();
160 let gmm = GuestMemoryMmap::from_ranges(®ions).unwrap();
161 let gm = GuestMemoryMmapAtomic::new(gmm);
162 let mem = gm.memory();
163
164 for region in mem.iter() {
165 assert_eq!(region.len(), region_size as GuestUsize);
166 }
167
168 for region in mem.iter() {
169 iterated_regions.push((region.start_addr(), region.len() as usize));
170 }
171 assert_eq!(regions, iterated_regions);
172 assert_eq!(mem.num_regions(), 2);
173 assert!(mem.find_region(GuestAddress(0x1000)).is_some());
174 assert!(mem.find_region(GuestAddress(0x10000)).is_none());
175
176 assert!(regions
177 .iter()
178 .map(|x| (x.0, x.1))
179 .eq(iterated_regions.iter().copied()));
180
181 let mem2 = mem.into_inner();
182 for region in mem2.iter() {
183 assert_eq!(region.len(), region_size as GuestUsize);
184 }
185 assert_eq!(mem2.num_regions(), 2);
186 assert!(mem2.find_region(GuestAddress(0x1000)).is_some());
187 assert!(mem2.find_region(GuestAddress(0x10000)).is_none());
188
189 assert!(regions
190 .iter()
191 .map(|x| (x.0, x.1))
192 .eq(iterated_regions.iter().copied()));
193
194 let mem3 = mem2.memory();
195 for region in mem3.iter() {
196 assert_eq!(region.len(), region_size as GuestUsize);
197 }
198 assert_eq!(mem3.num_regions(), 2);
199 assert!(mem3.find_region(GuestAddress(0x1000)).is_some());
200 assert!(mem3.find_region(GuestAddress(0x10000)).is_none());
201 }
202
203 #[test]
204 fn test_clone_guard() {
205 let region_size = 0x400;
206 let regions = vec![
207 (GuestAddress(0x0), region_size),
208 (GuestAddress(0x1000), region_size),
209 ];
210 let gmm = GuestMemoryMmap::from_ranges(®ions).unwrap();
211 let gm = GuestMemoryMmapAtomic::new(gmm);
212 let mem = {
213 let guard1 = gm.memory();
214 Clone::clone(&guard1)
215 };
216 assert_eq!(mem.num_regions(), 2);
217 }
218
219 #[test]
220 fn test_atomic_hotplug() {
221 let region_size = 0x1000;
222 let regions = vec![
223 (GuestAddress(0x0), region_size),
224 (GuestAddress(0x10_0000), region_size),
225 ];
226 let mut gmm = Arc::new(GuestMemoryMmap::from_ranges(®ions).unwrap());
227 let gm: GuestMemoryAtomic<_> = gmm.clone().into();
228 let mem_orig = gm.memory();
229 assert_eq!(mem_orig.num_regions(), 2);
230
231 {
232 let guard = gm.lock().unwrap();
233 let new_gmm = Arc::make_mut(&mut gmm);
234 let mmap = Arc::new(
235 GuestRegionMmap::new(MmapRegion::new(0x1000).unwrap(), GuestAddress(0x8000))
236 .unwrap(),
237 );
238 let new_gmm = new_gmm.insert_region(mmap).unwrap();
239 let mmap = Arc::new(
240 GuestRegionMmap::new(MmapRegion::new(0x1000).unwrap(), GuestAddress(0x4000))
241 .unwrap(),
242 );
243 let new_gmm = new_gmm.insert_region(mmap).unwrap();
244 let mmap = Arc::new(
245 GuestRegionMmap::new(MmapRegion::new(0x1000).unwrap(), GuestAddress(0xc000))
246 .unwrap(),
247 );
248 let new_gmm = new_gmm.insert_region(mmap).unwrap();
249 let mmap = Arc::new(
250 GuestRegionMmap::new(MmapRegion::new(0x1000).unwrap(), GuestAddress(0xc000))
251 .unwrap(),
252 );
253 new_gmm.insert_region(mmap).unwrap_err();
254 guard.replace(new_gmm);
255 }
256
257 assert_eq!(mem_orig.num_regions(), 2);
258 let mem = gm.memory();
259 assert_eq!(mem.num_regions(), 5);
260 }
261}