shadow_rs/host/
futex_table.rs
1use std::collections::HashMap;
2use std::collections::hash_map::Entry;
3
4use shadow_shim_helper_rs::syscall_types::ManagedPhysicalMemoryAddr;
5use shadow_shim_helper_rs::util::SyncSendPointer;
6
7use crate::cshadow as c;
8use crate::utility::ObjectCounter;
9
10pub struct FutexTable {
12 futexes: HashMap<ManagedPhysicalMemoryAddr, FutexRef>,
15 _counter: ObjectCounter,
16}
17
18impl FutexTable {
19 #[allow(clippy::new_without_default)]
20 pub fn new() -> Self {
21 Self {
22 futexes: HashMap::new(),
23 _counter: ObjectCounter::new("FutexTable"),
24 }
25 }
26
27 pub fn add(&mut self, futex: FutexRef) -> Result<(), FutexRef> {
30 let addr = futex.physical_addr();
31
32 match self.futexes.entry(addr) {
33 Entry::Occupied(_) => Err(futex),
34 Entry::Vacant(x) => {
35 x.insert(futex);
36 Ok(())
37 }
38 }
39 }
40
41 pub fn remove(&mut self, addr: ManagedPhysicalMemoryAddr) -> Option<FutexRef> {
42 self.futexes.remove(&addr)
43 }
44
45 pub fn get(&self, addr: ManagedPhysicalMemoryAddr) -> Option<&FutexRef> {
46 self.futexes.get(&addr)
47 }
48}
49
50pub struct FutexRef(SyncSendPointer<c::Futex>);
52
53impl FutexRef {
54 pub unsafe fn new(ptr: *mut c::Futex) -> Self {
60 debug_assert!(!ptr.is_null());
61 Self(unsafe { SyncSendPointer::new(ptr) })
62 }
63
64 pub fn ptr(&self) -> *mut c::Futex {
65 self.0.ptr()
66 }
67
68 pub fn physical_addr(&self) -> ManagedPhysicalMemoryAddr {
69 unsafe { c::futex_getAddress(self.ptr()) }
70 }
71
72 pub fn wake(&self, num_wakeups: libc::c_uint) -> libc::c_uint {
73 unsafe { c::futex_wake(self.ptr(), num_wakeups) }
74 }
75}
76
77impl std::ops::Drop for FutexRef {
78 fn drop(&mut self) {
79 unsafe { c::futex_unref(self.0.ptr()) };
80 }
81}
82
83mod export {
84 use super::*;
85
86 #[unsafe(no_mangle)]
88 pub unsafe extern "C-unwind" fn futextable_add(
89 table: *mut FutexTable,
90 futex: *mut c::Futex,
91 ) -> bool {
92 let table = unsafe { table.as_mut() }.unwrap();
93
94 assert!(!futex.is_null());
95 unsafe { c::futex_ref(futex) };
96 let futex = unsafe { FutexRef::new(futex) };
97
98 table.add(futex).is_ok()
99 }
100
101 #[unsafe(no_mangle)]
102 pub unsafe extern "C-unwind" fn futextable_remove(
103 table: *mut FutexTable,
104 addr: ManagedPhysicalMemoryAddr,
105 ) -> bool {
106 let table = unsafe { table.as_mut() }.unwrap();
107 table.remove(addr).is_some()
108 }
109
110 #[unsafe(no_mangle)]
113 pub unsafe extern "C-unwind" fn futextable_get(
114 table: *mut FutexTable,
115 addr: ManagedPhysicalMemoryAddr,
116 ) -> *mut c::Futex {
117 let table = unsafe { table.as_mut() }.unwrap();
118 table
119 .get(addr)
120 .map(|x| x.ptr())
121 .unwrap_or(std::ptr::null_mut())
122 }
123}