sel4_sync/
mutex.rs

1//
2// Copyright 2023, Colias Group, LLC
3// Copyright (c) 2020 Arm Limited
4//
5// SPDX-License-Identifier: MIT
6//
7
8use 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; // TODO
29
30    #[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; // TODO
77
78    #[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; // TODO
106
107    #[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
123// // //
124
125struct 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}