]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/itron/mutex.rs
Auto merge of #105436 - nnethercote:inline-place_contents_drop_state_cannot_differ...
[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 /// Create a mutex object. This function never panics.
15 fn new_mtx() -> Result<abi::ID, ItronError> {
16     ItronError::err_if_negative(unsafe {
17         abi::acre_mtx(&abi::T_CMTX {
18             // Priority inheritance mutex
19             mtxatr: abi::TA_INHERIT,
20             // Unused
21             ceilpri: 0,
22         })
23     })
24 }
25
26 impl Mutex {
27     #[inline]
28     pub const fn new() -> Mutex {
29         Mutex { mtx: SpinIdOnceCell::new() }
30     }
31
32     /// Get the inner mutex's ID, which is lazily created.
33     fn raw(&self) -> abi::ID {
34         match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) {
35             Ok((id, ())) => id,
36             Err(e) => fail(e, &"acre_mtx"),
37         }
38     }
39
40     pub fn lock(&self) {
41         let mtx = self.raw();
42         expect_success(unsafe { abi::loc_mtx(mtx) }, &"loc_mtx");
43     }
44
45     pub unsafe fn unlock(&self) {
46         let mtx = unsafe { self.mtx.get_unchecked().0 };
47         expect_success_aborting(unsafe { abi::unl_mtx(mtx) }, &"unl_mtx");
48     }
49
50     pub fn try_lock(&self) -> bool {
51         let mtx = self.raw();
52         match unsafe { abi::ploc_mtx(mtx) } {
53             abi::E_TMOUT => false,
54             er => {
55                 expect_success(er, &"ploc_mtx");
56                 true
57             }
58         }
59     }
60 }
61
62 impl Drop for Mutex {
63     fn drop(&mut self) {
64         if let Some(mtx) = self.mtx.get().map(|x| x.0) {
65             expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx");
66         }
67     }
68 }
69
70 pub(super) struct MutexGuard<'a>(&'a Mutex);
71
72 impl<'a> MutexGuard<'a> {
73     #[inline]
74     pub(super) fn lock(x: &'a Mutex) -> Self {
75         x.lock();
76         Self(x)
77     }
78 }
79
80 impl Drop for MutexGuard<'_> {
81     #[inline]
82     fn drop(&mut self) {
83         unsafe { self.0.unlock() };
84     }
85 }