55//! [`crossbeam-channel`](https://docs.rs/crossbeam-channel/latest/crossbeam_channel/), in as much
66//! as it makes sense.
77
8- use core:: {
9- cell:: UnsafeCell ,
10- fmt,
11- marker:: PhantomData ,
12- ops:: { Deref , DerefMut } ,
13- } ;
14-
15- use crate :: time:: { Forever , NoWait } ;
16- use crate :: sys:: sync as sys;
17-
188// Channels are currently only available with allocation. Bounded channels later might be
199// available.
2010#[ cfg( CONFIG_RUST_ALLOC ) ]
@@ -38,239 +28,12 @@ pub mod atomic {
3828#[ cfg( CONFIG_RUST_ALLOC ) ]
3929pub use portable_atomic_util:: Arc ;
4030
41- // Channels are currently only available with allocation. Bounded channels later might be
42- // available.
43-
44- /// Until poisoning is implemented, mutexes never return an error, and we just get back the guard.
45- pub type LockResult < Guard > = Result < Guard , ( ) > ;
46-
47- /// The return type from [`Mutex::try_lock`].
48- ///
49- /// The error indicates the reason for the failure. Until poisoning is
50- /// implemented, there is only a single type of failure.
51- pub type TryLockResult < Guard > = Result < Guard , TryLockError > ;
52-
53- /// An enumeration of possible errors associated with a [`TryLockResult`].
54- ///
55- /// Note that until Poisoning is implemented, there is only one value of this.
56- pub enum TryLockError {
57- /// The lock could not be acquired at this time because the operation would otherwise block.
58- WouldBlock ,
59- }
60-
61- /// A mutual exclusion primitive useful for protecting shared data.
62- ///
63- /// This mutex will block threads waiting for the lock to become available. This is modeled after
64- /// [`std::sync::Mutex`](https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html), and attempts
65- /// to implement that API as closely as makes sense on Zephyr. Currently, it has the following
66- /// differences:
67- /// - Poisoning: This does not yet implement poisoning, as there is no way to recover from panic at
68- /// this time on Zephyr.
69- /// - Allocation: `new` is not yet provided, and will be provided once kernel object pools are
70- /// implemented. Please use `new_from` which takes a reference to a statically allocated
71- /// `sys::Mutex`.
72- pub struct Mutex < T : ?Sized > {
73- inner : sys:: Mutex ,
74- // poison: ...
75- data : UnsafeCell < T > ,
76- }
77-
78- // At least if correctly done, the Mutex provides for Send and Sync as long as the inner data
79- // supports Send.
80- unsafe impl < T : ?Sized + Send > Send for Mutex < T > { }
81- unsafe impl < T : ?Sized + Send > Sync for Mutex < T > { }
82-
83- impl < T > fmt:: Debug for Mutex < T > {
84- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
85- write ! ( f, "Mutex {:?}" , self . inner)
86- }
87- }
88-
89- /// An RAII implementation of a "scoped lock" of a mutex. When this structure is dropped (faslls
90- /// out of scope), the lock will be unlocked.
91- ///
92- /// The data protected by the mutex can be accessed through this guard via its [`Deref`] and
93- /// [`DerefMut`] implementations.
94- ///
95- /// This structure is created by the [`lock`] and [`try_lock`] methods on [`Mutex`].
96- ///
97- /// [`lock`]: Mutex::lock
98- /// [`try_lock`]: Mutex::try_lock
99- ///
100- /// Taken directly from
101- /// [`std::sync::MutexGuard`](https://doc.rust-lang.org/stable/std/sync/struct.MutexGuard.html).
102- pub struct MutexGuard < ' a , T : ?Sized + ' a > {
103- lock : & ' a Mutex < T > ,
104- // until <https://github.com/rust-lang/rust/issues/68318> is implemented, we have to mark unsend
105- // explicitly. This can be done by holding Phantom data with an unsafe cell in it.
106- _nosend : PhantomData < UnsafeCell < ( ) > > ,
107- }
108-
109- // Make sure the guard doesn't get sent.
110- // Negative trait bounds are unstable, see marker above.
111- // impl<T: ?Sized> !Send for MutexGuard<'_, T> {}
112- unsafe impl < T : ?Sized + Sync > Sync for MutexGuard < ' _ , T > { }
31+ mod mutex;
11332
114- impl < T > Mutex < T > {
115- /// Construct a new wrapped Mutex, using the given underlying sys mutex. This is different that
116- /// `std::sync::Mutex` in that in Zephyr, objects are frequently allocated statically, and the
117- /// sys Mutex will be taken by this structure. It is safe to share the underlying Mutex between
118- /// different items, but without careful use, it is easy to deadlock, so it is not recommended.
119- pub const fn new_from ( t : T , raw_mutex : sys:: Mutex ) -> Mutex < T > {
120- Mutex { inner : raw_mutex, data : UnsafeCell :: new ( t) }
121- }
122-
123- /// Construct a new Mutex, dynamically allocating the underlying sys Mutex.
124- #[ cfg( CONFIG_RUST_ALLOC ) ]
125- pub fn new ( t : T ) -> Mutex < T > {
126- Mutex :: new_from ( t, sys:: Mutex :: new ( ) . unwrap ( ) )
127- }
128- }
129-
130- impl < T : ?Sized > Mutex < T > {
131- /// Acquires a mutex, blocking the current thread until it is able to do so.
132- ///
133- /// This function will block the local thread until it is available to acquire the mutex. Upon
134- /// returning, the thread is the only thread with the lock held. An RAII guard is returned to
135- /// allow scoped unlock of the lock. When the guard goes out of scope, the mutex will be
136- /// unlocked.
137- ///
138- /// In `std`, an attempt to lock a mutex by a thread that already holds the mutex is
139- /// unspecified. Zephyr explicitly supports this behavior, by simply incrementing a lock
140- /// count.
141- pub fn lock ( & self ) -> LockResult < MutexGuard < ' _ , T > > {
142- // With `Forever`, should never return an error.
143- self . inner . lock ( Forever ) . unwrap ( ) ;
144- unsafe {
145- Ok ( MutexGuard :: new ( self ) )
146- }
147- }
148-
149- /// Attempts to acquire this lock.
150- ///
151- /// If the lock could not be acquired at this time, then [`Err`] is returned. Otherwise, an RAII
152- /// guard is returned. The lock will be unlocked when the guard is dropped.
153- ///
154- /// This function does not block.
155- pub fn try_lock ( & self ) -> TryLockResult < MutexGuard < ' _ , T > > {
156- match self . inner . lock ( NoWait ) {
157- Ok ( ( ) ) => {
158- unsafe {
159- Ok ( MutexGuard :: new ( self ) )
160- }
161- }
162- // TODO: It might be better to distinguish these errors, and only return the WouldBlock
163- // if that is the corresponding error. But, the lock shouldn't fail in Zephyr.
164- Err ( _) => {
165- Err ( TryLockError :: WouldBlock )
166- }
167- }
168- }
169- }
170-
171- impl < ' mutex , T : ?Sized > MutexGuard < ' mutex , T > {
172- unsafe fn new ( lock : & ' mutex Mutex < T > ) -> MutexGuard < ' mutex , T > {
173- // poison todo
174- MutexGuard { lock, _nosend : PhantomData }
175- }
176- }
177-
178- impl < T : ?Sized > Deref for MutexGuard < ' _ , T > {
179- type Target = T ;
180-
181- fn deref ( & self ) -> & T {
182- unsafe {
183- & * self . lock . data . get ( )
184- }
185- }
186- }
187-
188- impl < T : ?Sized > DerefMut for MutexGuard < ' _ , T > {
189- fn deref_mut ( & mut self ) -> & mut T {
190- unsafe { & mut * self . lock . data . get ( ) }
191- }
192- }
193-
194- impl < T : ?Sized > Drop for MutexGuard < ' _ , T > {
195- #[ inline]
196- fn drop ( & mut self ) {
197- self . lock . inner . unlock ( ) . unwrap ( ) ;
198- }
199- }
200-
201- /// Inspired by
202- /// [`std::sync::Condvar`](https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html),
203- /// implemented directly using `z_condvar` in Zephyr.
204- ///
205- /// Condition variables represent the ability to block a thread such that it consumes no CPU time
206- /// while waiting for an even to occur. Condition variables are typically associated with a
207- /// boolean predicate (a condition) and a mutex. The predicate is always verified inside of the
208- /// mutex before determining that a thread must block.
209- ///
210- /// Functions in this module will block the current **thread** of execution. Note that any attempt
211- /// to use multiple mutexces on the same condition variable may result in a runtime panic.
212- pub struct Condvar {
213- inner : sys:: Condvar ,
214- }
215-
216- impl Condvar {
217- /// Construct a new wrapped Condvar, using the given underlying `k_condvar`.
218- ///
219- /// This is different from `std::sync::Condvar` in that in Zephyr, objects are frequently
220- /// allocated statically, and the sys Condvar will be taken by this structure.
221- pub const fn new_from ( raw_condvar : sys:: Condvar ) -> Condvar {
222- Condvar { inner : raw_condvar }
223- }
224-
225- /// Construct a new Condvar, dynamically allocating the underlying Zephyr `k_condvar`.
226- #[ cfg( CONFIG_RUST_ALLOC ) ]
227- pub fn new ( ) -> Condvar {
228- Condvar :: new_from ( sys:: Condvar :: new ( ) . unwrap ( ) )
229- }
230-
231- /// Blocks the current thread until this conditional variable receives a notification.
232- ///
233- /// This function will automatically unlock the mutex specified (represented by `guard`) and
234- /// block the current thread. This means that any calls to `notify_one` or `notify_all` which
235- /// happen logically after the mutex is unlocked are candidates to wake this thread up. When
236- /// this function call returns, the lock specified will have been re-equired.
237- ///
238- /// Note that this function is susceptable to spurious wakeups. Condition variables normally
239- /// have a boolean predicate associated with them, and the predicate must always be checked
240- /// each time this function returns to protect against spurious wakeups.
241- pub fn wait < ' a , T > ( & self , guard : MutexGuard < ' a , T > ) -> LockResult < MutexGuard < ' a , T > > {
242- self . inner . wait ( & guard. lock . inner ) ;
243- Ok ( guard)
244- }
245-
246- // TODO: wait_while
247- // TODO: wait_timeout_ms
248- // TODO: wait_timeout
249- // TODO: wait_timeout_while
250-
251- /// Wakes up one blocked thread on this condvar.
252- ///
253- /// If there is a blocked thread on this condition variable, then it will be woken up from its
254- /// call to `wait` or `wait_timeout`. Calls to `notify_one` are not buffered in any way.
255- ///
256- /// To wakeup all threads, see `notify_all`.
257- pub fn notify_one ( & self ) {
258- self . inner . notify_one ( ) ;
259- }
260-
261- /// Wakes up all blocked threads on this condvar.
262- ///
263- /// This methods will ensure that any current waiters on the condition variable are awoken.
264- /// Calls to `notify_all()` are not buffered in any way.
265- ///
266- /// To wake up only one thread, see `notify_one`.
267- pub fn notify_all ( & self ) {
268- self . inner . notify_all ( ) ;
269- }
270- }
271-
272- impl fmt:: Debug for Condvar {
273- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
274- write ! ( f, "Condvar {:?}" , self . inner)
275- }
276- }
33+ pub use mutex:: {
34+ Mutex ,
35+ MutexGuard ,
36+ Condvar ,
37+ LockResult ,
38+ TryLockResult ,
39+ } ;
0 commit comments