shadow_rs/host/syscall/
condition.rs
1use 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 if !condition.c_ptr.ptr().is_null() {
159 unsafe { cshadow::syscallcondition_unref(condition.c_ptr.ptr()) }
160 }
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}