]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/itron/mutex.rs
Auto merge of #100759 - fee1-dead-contrib:const_eval_select_real_intrinsic, r=oli...
[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     /// Get the inner mutex's ID, which is lazily created.
35     fn raw(&self) -> abi::ID {
36         match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) {
37             Ok((id, ())) => id,
38             Err(e) => fail(e, &"acre_mtx"),
39         }
40     }
41
42     pub unsafe fn lock(&self) {
43         let mtx = self.raw();
44         expect_success(unsafe { abi::loc_mtx(mtx) }, &"loc_mtx");
45     }
46
47     pub unsafe fn unlock(&self) {
48         let mtx = unsafe { self.mtx.get_unchecked().0 };
49         expect_success_aborting(unsafe { abi::unl_mtx(mtx) }, &"unl_mtx");
50     }
51
52     pub unsafe fn try_lock(&self) -> bool {
53         let mtx = self.raw();
54         match unsafe { abi::ploc_mtx(mtx) } {
55             abi::E_TMOUT => false,
56             er => {
57                 expect_success(er, &"ploc_mtx");
58                 true
59             }
60         }
61     }
62 }
63
64 impl Drop for Mutex {
65     fn drop(&mut self) {
66         if let Some(mtx) = self.mtx.get().map(|x| x.0) {
67             expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx");
68         }
69     }
70 }
71
72 pub(super) struct MutexGuard<'a>(&'a Mutex);
73
74 impl<'a> MutexGuard<'a> {
75     #[inline]
76     pub(super) fn lock(x: &'a Mutex) -> Self {
77         unsafe { x.lock() };
78         Self(x)
79     }
80 }
81
82 impl Drop for MutexGuard<'_> {
83     #[inline]
84     fn drop(&mut self) {
85         unsafe { self.0.unlock() };
86     }
87 }