]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/itron/mutex.rs
Rollup merge of #97633 - mkroening:object-osabi, r=petrochenkov
[rust.git] / library / std / src / sys / itron / mutex.rs
1 //! Mutex implementation backed by μITRON mutexes. Assumes `acre_mtx` and
2 //! `TA_INHERIT` are available.
3 use super::{
4     abi,
5     error::{expect_success, expect_success_aborting, fail, ItronError},
6     spin::SpinIdOnceCell,
7 };
8
9 pub struct Mutex {
10     /// The ID of the underlying mutex object
11     mtx: SpinIdOnceCell<()>,
12 }
13
14 pub type MovableMutex = Mutex;
15
16 /// Create a mutex object. This function never panics.
17 fn new_mtx() -> Result<abi::ID, ItronError> {
18     ItronError::err_if_negative(unsafe {
19         abi::acre_mtx(&abi::T_CMTX {
20             // Priority inheritance mutex
21             mtxatr: abi::TA_INHERIT,
22             // Unused
23             ceilpri: 0,
24         })
25     })
26 }
27
28 impl Mutex {
29     #[inline]
30     pub const fn new() -> Mutex {
31         Mutex { mtx: SpinIdOnceCell::new() }
32     }
33
34     pub unsafe fn init(&mut self) {
35         // Initialize `self.mtx` eagerly
36         let id = new_mtx().unwrap_or_else(|e| fail(e, &"acre_mtx"));
37         unsafe { self.mtx.set_unchecked((id, ())) };
38     }
39
40     /// Get the inner mutex's ID, which is lazily created.
41     fn raw(&self) -> abi::ID {
42         match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) {
43             Ok((id, ())) => id,
44             Err(e) => fail(e, &"acre_mtx"),
45         }
46     }
47
48     pub unsafe fn lock(&self) {
49         let mtx = self.raw();
50         expect_success(unsafe { abi::loc_mtx(mtx) }, &"loc_mtx");
51     }
52
53     pub unsafe fn unlock(&self) {
54         let mtx = unsafe { self.mtx.get_unchecked().0 };
55         expect_success_aborting(unsafe { abi::unl_mtx(mtx) }, &"unl_mtx");
56     }
57
58     pub unsafe fn try_lock(&self) -> bool {
59         let mtx = self.raw();
60         match unsafe { abi::ploc_mtx(mtx) } {
61             abi::E_TMOUT => false,
62             er => {
63                 expect_success(er, &"ploc_mtx");
64                 true
65             }
66         }
67     }
68 }
69
70 impl Drop for Mutex {
71     fn drop(&mut self) {
72         if let Some(mtx) = self.mtx.get().map(|x| x.0) {
73             expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx");
74         }
75     }
76 }
77
78 pub(super) struct MutexGuard<'a>(&'a Mutex);
79
80 impl<'a> MutexGuard<'a> {
81     #[inline]
82     pub(super) fn lock(x: &'a Mutex) -> Self {
83         unsafe { x.lock() };
84         Self(x)
85     }
86 }
87
88 impl Drop for MutexGuard<'_> {
89     #[inline]
90     fn drop(&mut self) {
91         unsafe { self.0.unlock() };
92     }
93 }