1use crate::error::Result;
8use crate::ffi;
9use crate::os::id::OsalId;
10use crate::os::time::OsTime;
11use crate::os::util::c_name_from_str;
12use crate::string_from_c_buf;
13use crate::status::check;
14use core::mem::MaybeUninit;
15use core::ops::Drop;
16use heapless::String;
17
18#[derive(Debug, Clone)]
20pub struct MutexProp {
21 pub name: String<{ ffi::OS_MAX_API_NAME as usize }>,
23 pub creator: OsalId,
25}
26
27#[derive(Debug)]
31pub struct Mutex {
32 id: ffi::osal_id_t,
33}
34
35impl Mutex {
36 pub fn new(name: &str) -> Result<Self> {
41 let c_name = c_name_from_str(name)?;
42 let mut sem_id = MaybeUninit::uninit();
43 let status = unsafe { ffi::OS_MutSemCreate(sem_id.as_mut_ptr(), c_name.as_ptr(), 0) };
44 check(status)?;
45 Ok(Self {
46 id: unsafe { sem_id.assume_init() },
47 })
48 }
49
50 pub fn lock(&'_ self) -> Result<MutexGuard<'_>> {
55 check(unsafe { ffi::OS_MutSemTake(self.id) })?;
56 Ok(MutexGuard { mutex: self })
57 }
58
59 pub fn get_id_by_name(name: &str) -> Result<OsalId> {
61 let c_name = c_name_from_str(name)?;
62 let mut sem_id = MaybeUninit::uninit();
63 check(unsafe { ffi::OS_MutSemGetIdByName(sem_id.as_mut_ptr(), c_name.as_ptr()) })?;
64 Ok(OsalId(unsafe { sem_id.assume_init() }))
65 }
66
67 pub fn get_info(&self) -> Result<MutexProp> {
69 let mut prop = MaybeUninit::<ffi::OS_mut_sem_prop_t>::uninit();
70 check(unsafe { ffi::OS_MutSemGetInfo(self.id, prop.as_mut_ptr()) })?;
71 let prop = unsafe { prop.assume_init() };
72
73 Ok(MutexProp {
74 name: string_from_c_buf(&prop.name)?,
75 creator: OsalId(prop.creator),
76 })
77 }
78}
79
80impl Drop for Mutex {
81 fn drop(&mut self) {
82 let _ = unsafe { ffi::OS_MutSemDelete(self.id) };
83 }
84}
85
86#[derive(Debug)]
90#[must_use = "if unused the Mutex will immediately unlock"]
91pub struct MutexGuard<'a> {
92 mutex: &'a Mutex,
93}
94
95impl<'a> Drop for MutexGuard<'a> {
96 fn drop(&mut self) {
98 let _ = unsafe { ffi::OS_MutSemGive(self.mutex.id) };
99 }
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub enum SemState {
105 Empty,
107 Full,
109}
110
111impl SemState {
112 fn as_u32(self) -> u32 {
113 match self {
114 SemState::Empty => 0,
115 SemState::Full => 1,
116 }
117 }
118}
119
120#[derive(Debug, Clone)]
122pub struct BinSemProp {
123 pub name: String<{ ffi::OS_MAX_API_NAME as usize }>,
125 pub creator: OsalId,
127 pub value: i32,
129}
130
131#[derive(Debug)]
133pub struct BinSem {
134 id: ffi::osal_id_t,
135}
136
137impl BinSem {
138 pub fn new(name: &str, initial_value: SemState) -> Result<Self> {
144 let c_name = c_name_from_str(name)?;
145 let mut sem_id = MaybeUninit::uninit();
146 let status = unsafe {
147 ffi::OS_BinSemCreate(sem_id.as_mut_ptr(), c_name.as_ptr(), initial_value.as_u32(), 0)
148 };
149 check(status)?;
150 Ok(Self {
151 id: unsafe { sem_id.assume_init() },
152 })
153 }
154
155 pub fn give(&self) -> Result<()> {
157 check(unsafe { ffi::OS_BinSemGive(self.id) })?;
158 Ok(())
159 }
160
161 pub fn take(&self) -> Result<()> {
163 check(unsafe { ffi::OS_BinSemTake(self.id) })?;
164 Ok(())
165 }
166
167 pub fn flush(&self) -> Result<()> {
171 check(unsafe { ffi::OS_BinSemFlush(self.id) })?;
172 Ok(())
173 }
174
175 pub fn timed_wait(&self, timeout_ms: u32) -> Result<()> {
180 check(unsafe { ffi::OS_BinSemTimedWait(self.id, timeout_ms) })?;
181 Ok(())
182 }
183
184 pub fn get_id_by_name(name: &str) -> Result<OsalId> {
186 let c_name = c_name_from_str(name)?;
187 let mut sem_id = MaybeUninit::uninit();
188 check(unsafe { ffi::OS_BinSemGetIdByName(sem_id.as_mut_ptr(), c_name.as_ptr()) })?;
189 Ok(OsalId(unsafe { sem_id.assume_init() }))
190 }
191
192 pub fn get_info(&self) -> Result<BinSemProp> {
194 let mut prop = MaybeUninit::<ffi::OS_bin_sem_prop_t>::uninit();
195 check(unsafe { ffi::OS_BinSemGetInfo(self.id, prop.as_mut_ptr()) })?;
196 let prop = unsafe { prop.assume_init() };
197
198 Ok(BinSemProp {
199 name: string_from_c_buf(&prop.name)?,
200 creator: OsalId(prop.creator),
201 value: prop.value,
202 })
203 }
204}
205
206impl Drop for BinSem {
207 fn drop(&mut self) {
208 let _ = unsafe { ffi::OS_BinSemDelete(self.id) };
209 }
210}
211
212#[derive(Debug, Clone)]
214pub struct CountSemProp {
215 pub name: String<{ ffi::OS_MAX_API_NAME as usize }>,
217 pub creator: OsalId,
219 pub value: i32,
221}
222
223#[derive(Debug)]
225pub struct CountSem {
226 id: ffi::osal_id_t,
227}
228
229impl CountSem {
230 pub fn new(name: &str, initial_value: u32) -> Result<Self> {
239 let c_name = c_name_from_str(name)?;
240 let mut sem_id = MaybeUninit::uninit();
241 let status = unsafe {
242 ffi::OS_CountSemCreate(sem_id.as_mut_ptr(), c_name.as_ptr(), initial_value, 0)
243 };
244 check(status)?;
245 Ok(Self {
246 id: unsafe { sem_id.assume_init() },
247 })
248 }
249
250 pub fn give(&self) -> Result<()> {
252 check(unsafe { ffi::OS_CountSemGive(self.id) })?;
253 Ok(())
254 }
255
256 pub fn take(&self) -> Result<()> {
258 check(unsafe { ffi::OS_CountSemTake(self.id) })?;
259 Ok(())
260 }
261
262 pub fn timed_wait(&self, timeout_ms: u32) -> Result<()> {
267 check(unsafe { ffi::OS_CountSemTimedWait(self.id, timeout_ms) })?;
268 Ok(())
269 }
270
271 pub fn get_id_by_name(name: &str) -> Result<OsalId> {
273 let c_name = c_name_from_str(name)?;
274 let mut sem_id = MaybeUninit::uninit();
275 check(unsafe { ffi::OS_CountSemGetIdByName(sem_id.as_mut_ptr(), c_name.as_ptr()) })?;
276 Ok(OsalId(unsafe { sem_id.assume_init() }))
277 }
278
279 pub fn get_info(&self) -> Result<CountSemProp> {
281 let mut prop = MaybeUninit::<ffi::OS_count_sem_prop_t>::uninit();
282 check(unsafe { ffi::OS_CountSemGetInfo(self.id, prop.as_mut_ptr()) })?;
283 let prop = unsafe { prop.assume_init() };
284
285 Ok(CountSemProp {
286 name: string_from_c_buf(&prop.name)?,
287 creator: OsalId(prop.creator),
288 value: prop.value,
289 })
290 }
291}
292
293impl Drop for CountSem {
294 fn drop(&mut self) {
295 let _ = unsafe { ffi::OS_CountSemDelete(self.id) };
296 }
297}
298
299#[derive(Debug, Clone)]
301pub struct CondVarProp {
302 pub name: String<{ ffi::OS_MAX_API_NAME as usize }>,
304 pub creator: OsalId,
306}
307
308#[derive(Debug)]
310pub struct CondVar {
311 id: ffi::osal_id_t,
312}
313
314impl CondVar {
315 pub fn new(name: &str) -> Result<Self> {
317 let c_name = c_name_from_str(name)?;
318 let mut var_id = MaybeUninit::uninit();
319 check(unsafe { ffi::OS_CondVarCreate(var_id.as_mut_ptr(), c_name.as_ptr(), 0) })?;
320 Ok(Self {
321 id: unsafe { var_id.assume_init() },
322 })
323 }
324
325 pub fn signal(&self) -> Result<()> {
327 check(unsafe { ffi::OS_CondVarSignal(self.id) })?;
328 Ok(())
329 }
330
331 pub fn broadcast(&self) -> Result<()> {
333 check(unsafe { ffi::OS_CondVarBroadcast(self.id) })?;
334 Ok(())
335 }
336
337 pub fn wait(&self, _guard: MutexGuard) -> Result<()> {
345 check(unsafe { ffi::OS_CondVarWait(self.id) })?;
346 Ok(())
347 }
348
349 pub fn timed_wait(&self, _guard: MutexGuard, abstime: OsTime) -> Result<()> {
351 check(unsafe { ffi::OS_CondVarTimedWait(self.id, &abstime.0) })?;
352 Ok(())
353 }
354
355 pub fn get_id_by_name(name: &str) -> Result<OsalId> {
357 let c_name = c_name_from_str(name)?;
358 let mut var_id = MaybeUninit::uninit();
359 check(unsafe { ffi::OS_CondVarGetIdByName(var_id.as_mut_ptr(), c_name.as_ptr()) })?;
360 Ok(OsalId(unsafe { var_id.assume_init() }))
361 }
362
363 pub fn get_info(&self) -> Result<CondVarProp> {
365 let mut prop = MaybeUninit::<ffi::OS_condvar_prop_t>::uninit();
366 check(unsafe { ffi::OS_CondVarGetInfo(self.id, prop.as_mut_ptr()) })?;
367 let prop = unsafe { prop.assume_init() };
368
369 Ok(CondVarProp {
370 name: string_from_c_buf(&prop.name)?,
371 creator: OsalId(prop.creator),
372 })
373 }
374}
375
376impl Drop for CondVar {
377 fn drop(&mut self) {
378 let _ = unsafe { ffi::OS_CondVarDelete(self.id) };
379 }
380}