shadow_rs/host/syscall/
condition.rs1use std::marker::PhantomData;
2
3use linux_api::signal::Signal;
4use shadow_shim_helper_rs::emulated_time::EmulatedTime;
5use shadow_shim_helper_rs::util::SendPointer;
6
7use crate::cshadow;
8use crate::host::descriptor::OpenFile;
9use crate::host::host::Host;
10use crate::host::syscall::Trigger;
11
12#[derive(Debug, PartialEq, Eq)]
14pub struct SyscallConditionRef<'a> {
15    c_ptr: SendPointer<cshadow::SysCallCondition>,
16    _phantom: PhantomData<&'a ()>,
17}
18
19impl SyscallConditionRef<'_> {
21    pub unsafe fn borrow_from_c(ptr: *mut cshadow::SysCallCondition) -> Self {
29        assert!(!ptr.is_null());
30        Self {
31            c_ptr: unsafe { SendPointer::new(ptr) },
32            _phantom: PhantomData,
33        }
34    }
35
36    pub fn active_file(&self) -> Option<&OpenFile> {
37        let file_ptr = unsafe { cshadow::syscallcondition_getActiveFile(self.c_ptr.ptr()) };
38        if file_ptr.is_null() {
39            return None;
40        }
41
42        Some(unsafe { file_ptr.as_ref() }.unwrap())
43    }
44
45    pub fn timeout(&self) -> Option<EmulatedTime> {
46        let timeout = unsafe { cshadow::syscallcondition_getTimeout(self.c_ptr.ptr()) };
47        EmulatedTime::from_c_emutime(timeout)
48    }
49}
50
51#[derive(Debug, PartialEq, Eq)]
53pub struct SyscallConditionRefMut<'a> {
54    condition: SyscallConditionRef<'a>,
55}
56
57impl SyscallConditionRefMut<'_> {
59    pub unsafe fn borrow_from_c(ptr: *mut cshadow::SysCallCondition) -> Self {
67        assert!(!ptr.is_null());
68        Self {
69            condition: unsafe { SyscallConditionRef::borrow_from_c(ptr) },
70        }
71    }
72
73    pub fn set_active_file(&mut self, file: OpenFile) {
74        let file_ptr = Box::into_raw(Box::new(file));
75        unsafe { cshadow::syscallcondition_setActiveFile(self.condition.c_ptr.ptr(), file_ptr) };
76    }
77
78    pub fn wakeup_for_signal(&mut self, host: &Host, signal: Signal) -> bool {
79        unsafe {
80            cshadow::syscallcondition_wakeupForSignal(
81                self.condition.c_ptr.ptr(),
82                host,
83                signal.into(),
84            )
85        }
86    }
87
88    pub fn set_timeout(&mut self, timeout: Option<EmulatedTime>) {
89        let timeout = EmulatedTime::to_c_emutime(timeout);
90        unsafe { cshadow::syscallcondition_setTimeout(self.c_ptr.ptr(), timeout) };
91    }
92}
93
94impl<'a> std::ops::Deref for SyscallConditionRefMut<'a> {
95    type Target = SyscallConditionRef<'a>;
96
97    fn deref(&self) -> &Self::Target {
98        &self.condition
99    }
100}
101
102#[derive(Debug, PartialEq, Eq)]
104pub struct SyscallCondition {
105    condition: Option<SyscallConditionRefMut<'static>>,
106}
107
108impl SyscallCondition {
109    pub unsafe fn consume_from_c(ptr: *mut cshadow::SysCallCondition) -> Self {
117        assert!(!ptr.is_null());
118        Self {
119            condition: Some(unsafe { SyscallConditionRefMut::borrow_from_c(ptr) }),
120        }
121    }
122
123    pub fn new(trigger: Trigger) -> Self {
127        SyscallCondition {
128            condition: Some(unsafe {
129                SyscallConditionRefMut::borrow_from_c(cshadow::syscallcondition_new(trigger.into()))
130            }),
131        }
132    }
133
134    pub fn new_from_wakeup_time(abs_wakeup_time: EmulatedTime) -> Self {
139        SyscallCondition {
140            condition: Some(unsafe {
141                SyscallConditionRefMut::borrow_from_c(cshadow::syscallcondition_newWithAbsTimeout(
142                    EmulatedTime::to_c_emutime(Some(abs_wakeup_time)),
143                ))
144            }),
145        }
146    }
147
148    pub fn into_inner(mut self) -> *mut cshadow::SysCallCondition {
150        let condition = self.condition.take().unwrap();
151        condition.c_ptr.ptr()
152    }
153}
154
155impl Drop for SyscallCondition {
156    fn drop(&mut self) {
157        if let Some(condition) = &self.condition
158            && !condition.c_ptr.ptr().is_null()
159        {
160            unsafe { cshadow::syscallcondition_unref(condition.c_ptr.ptr()) }
161        }
162    }
163}
164
165impl std::ops::Deref for SyscallCondition {
166    type Target = SyscallConditionRefMut<'static>;
167
168    fn deref(&self) -> &Self::Target {
169        self.condition.as_ref().unwrap()
170    }
171}
172
173impl std::ops::DerefMut for SyscallCondition {
174    fn deref_mut(&mut self) -> &mut Self::Target {
175        self.condition.as_mut().unwrap()
176    }
177}