sel4_sync/
mutex.rs
1use core::marker::PhantomData;
9use core::sync::atomic::{fence, AtomicIsize, Ordering};
10
11use sel4_immediate_sync_once_cell::ImmediateSyncOnceCell;
12
13pub struct RawNotificationMutex<_T = ()> {
14 inner: GenericRawMutex<sel4::cap::Notification>,
15 phantom: PhantomData<_T>,
16}
17
18impl RawNotificationMutex {
19 pub const fn new(nfn: sel4::cap::Notification) -> Self {
20 Self {
21 inner: GenericRawMutex::new(nfn),
22 phantom: PhantomData,
23 }
24 }
25}
26
27unsafe impl<_T> lock_api::RawMutex for RawNotificationMutex<_T> {
28 type GuardMarker = lock_api::GuardNoSend; #[allow(unreachable_code)]
31 #[allow(clippy::diverging_sub_expression)]
32 #[allow(clippy::declare_interior_mutable_const)]
33 const INIT: Self = {
34 let _: _T = unimplemented!();
35 unimplemented!()
36 };
37
38 fn lock(&self) {
39 self.inner.lock()
40 }
41
42 fn try_lock(&self) -> bool {
43 self.inner.try_lock()
44 }
45
46 unsafe fn unlock(&self) {
47 self.inner.unlock()
48 }
49}
50
51pub struct RawDeferredNotificationMutex(GenericRawMutex<DeferredNotification>);
52
53impl RawDeferredNotificationMutex {
54 pub const fn new() -> Self {
55 Self(GenericRawMutex::new(DeferredNotification::new()))
56 }
57
58 pub fn set_notification(
59 &self,
60 nfn: sel4::cap::Notification,
61 ) -> Result<(), NotificationAlreadySetError> {
62 self.0.nfn.set_notification(nfn)
63 }
64}
65
66#[derive(Debug, Copy, Clone, Eq, PartialEq)]
67pub struct NotificationAlreadySetError(());
68
69impl Default for RawDeferredNotificationMutex {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75unsafe impl lock_api::RawMutex for RawDeferredNotificationMutex {
76 type GuardMarker = lock_api::GuardNoSend; #[allow(clippy::declare_interior_mutable_const)]
79 const INIT: Self = Self::new();
80
81 fn lock(&self) {
82 self.0.lock()
83 }
84
85 fn try_lock(&self) -> bool {
86 self.0.try_lock()
87 }
88
89 unsafe fn unlock(&self) {
90 self.0.unlock()
91 }
92}
93
94pub struct RawLazyNotificationMutex<F = fn() -> sel4::cap::Notification>(
95 GenericRawMutex<LazyNotification<F>>,
96);
97
98impl<F> RawLazyNotificationMutex<F> {
99 pub const fn new(f: F) -> Self {
100 Self(GenericRawMutex::new(LazyNotification::new(f)))
101 }
102}
103
104unsafe impl<F: Fn() -> sel4::cap::Notification> lock_api::RawMutex for RawLazyNotificationMutex<F> {
105 type GuardMarker = lock_api::GuardNoSend; #[allow(clippy::declare_interior_mutable_const)]
108 const INIT: Self = unimplemented!();
109
110 fn lock(&self) {
111 self.0.lock()
112 }
113
114 fn try_lock(&self) -> bool {
115 self.0.try_lock()
116 }
117
118 unsafe fn unlock(&self) {
119 self.0.unlock()
120 }
121}
122
123struct GenericRawMutex<T> {
126 nfn: T,
127 value: AtomicIsize,
128}
129
130impl<T> GenericRawMutex<T> {
131 const fn new(nfn: T) -> Self {
132 Self {
133 nfn,
134 value: AtomicIsize::new(1),
135 }
136 }
137}
138
139trait GetNotification {
140 fn get_notification(&self) -> sel4::cap::Notification;
141}
142
143impl<T: GetNotification> GenericRawMutex<T> {
144 fn lock(&self) {
145 let old_value = self.value.fetch_sub(1, Ordering::Acquire);
146 if old_value <= 0 {
147 let _badge = self.nfn.get_notification().wait();
148 fence(Ordering::Acquire);
149 }
150 }
151
152 fn try_lock(&self) -> bool {
153 unimplemented!()
154 }
155
156 unsafe fn unlock(&self) {
157 let old_value = self.value.fetch_add(1, Ordering::Release);
158 if old_value < 0 {
159 self.nfn.get_notification().signal();
160 }
161 }
162}
163
164impl GetNotification for sel4::cap::Notification {
165 fn get_notification(&self) -> sel4::cap::Notification {
166 *self
167 }
168}
169
170struct DeferredNotification {
171 inner: ImmediateSyncOnceCell<sel4::cap::Notification>,
172}
173
174impl DeferredNotification {
175 const fn new() -> Self {
176 Self {
177 inner: ImmediateSyncOnceCell::new(),
178 }
179 }
180
181 fn set_notification(
182 &self,
183 nfn: sel4::cap::Notification,
184 ) -> Result<(), NotificationAlreadySetError> {
185 self.inner
186 .set(nfn)
187 .map_err(|_| NotificationAlreadySetError(()))
188 }
189}
190
191impl GetNotification for DeferredNotification {
192 fn get_notification(&self) -> sel4::cap::Notification {
193 *self.inner.get().unwrap()
194 }
195}
196
197struct LazyNotification<F> {
198 f: F,
199 state: ImmediateSyncOnceCell<sel4::cap::Notification>,
200}
201
202impl<F> LazyNotification<F> {
203 const fn new(f: F) -> Self {
204 Self {
205 f,
206 state: ImmediateSyncOnceCell::new(),
207 }
208 }
209}
210
211impl<F: Fn() -> sel4::cap::Notification> GetNotification for LazyNotification<F> {
212 fn get_notification(&self) -> sel4::cap::Notification {
213 match self.state.get() {
214 Some(nfn) => *nfn,
215 None => {
216 let _ = self.state.set((self.f)());
217 *self.state.get().unwrap()
218 }
219 }
220 }
221}