Skip to main content

netstack3_sync/
lib.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Synchronization primitives for Netstack3.
6
7#![no_std]
8#![warn(missing_docs, unreachable_patterns, unused)]
9
10extern crate alloc;
11#[cfg(any(test, feature = "rc-debug-names"))]
12extern crate std;
13
14#[cfg(not(loom))]
15pub(crate) use core::sync;
16#[cfg(loom)]
17pub(crate) use loom::sync;
18
19use net_types::ip::{GenericOverIp, Ip};
20
21// Re-export atomics module for loom compatibility in appropriate targets.
22pub use sync::atomic;
23
24pub mod once;
25pub mod rc;
26
27#[cfg(not(loom))]
28pub use inner::*;
29#[cfg(loom)]
30pub use inner_loom::*;
31
32#[cfg(not(loom))]
33mod inner {
34    use core::fmt;
35
36    /// A mutex assuming lock poisoning will never occur.
37    pub struct Mutex<T, R>(lock_api::Mutex<R, T>);
38
39    /// Lock guard for access to a [`Mutex`].
40    pub type LockGuard<'a, T, R> = lock_api::MutexGuard<'a, R, T>;
41
42    impl<T: Default, R: lock_api::RawMutex> Default for Mutex<T, R> {
43        #[inline]
44        fn default() -> Self {
45            Self(lock_api::Mutex::default())
46        }
47    }
48
49    impl<T: fmt::Debug, R: lock_api::RawMutex> fmt::Debug for Mutex<T, R> {
50        #[inline]
51        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52            let Self(m) = self;
53            m.fmt(f)
54        }
55    }
56
57    impl<T, R: lock_api::RawMutex> Mutex<T, R> {
58        /// Creates a new mutex in an unlocked state ready for use.
59        #[inline]
60        pub const fn new(t: T) -> Self {
61            Self(lock_api::Mutex::new(t))
62        }
63
64        /// Acquires a mutex, blocking the current thread until it is able to do
65        /// so.
66        ///
67        /// # Panics
68        ///
69        /// This method may panic if the calling thread is already holding the
70        /// lock.
71        #[inline]
72        pub fn lock(&self) -> LockGuard<'_, T, R> {
73            let Self(m) = self;
74            m.lock()
75        }
76
77        /// Consumes this mutex, returning the underlying data.
78        #[inline]
79        pub fn into_inner(self) -> T {
80            let Self(mutex) = self;
81            mutex.into_inner()
82        }
83
84        /// Returns a mutable reference to the underlying data.
85        ///
86        /// Since this call borrows the [`Mutex`] mutably, no actual locking
87        /// needs to take place.
88        #[inline]
89        pub fn get_mut(&mut self) -> &mut T {
90            let Self(mutex) = self;
91            mutex.get_mut()
92        }
93    }
94    /// A reader-writer lock assuming lock poisoning will never occur.
95    pub struct RwLock<T, R>(lock_api::RwLock<R, T>);
96
97    /// Lock guard for read access to a [`RwLock`].
98    pub type RwLockReadGuard<'a, T, R> = lock_api::RwLockReadGuard<'a, R, T>;
99
100    /// Lock guard for write access to a [`RwLock`].
101    pub type RwLockWriteGuard<'a, T, R> = lock_api::RwLockWriteGuard<'a, R, T>;
102
103    impl<T: Default, R: lock_api::RawRwLock> Default for RwLock<T, R> {
104        #[inline]
105        fn default() -> Self {
106            Self(lock_api::RwLock::default())
107        }
108    }
109
110    impl<T: fmt::Debug, R: lock_api::RawRwLock> fmt::Debug for RwLock<T, R> {
111        #[inline]
112        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113            let Self(rw) = self;
114            rw.fmt(f)
115        }
116    }
117
118    impl<T, R: lock_api::RawRwLock> RwLock<T, R> {
119        /// Creates a new instance of an `RwLock<T>` which is unlocked.
120        #[inline]
121        pub const fn new(t: T) -> Self {
122            Self(lock_api::RwLock::new(t))
123        }
124
125        /// Locks this rwlock with shared read access, blocking the current
126        /// thread until it can be acquired.
127        ///
128        /// # Panics
129        ///
130        /// This method may panic if the calling thread already holds the read
131        /// or write lock.
132        #[inline]
133        pub fn read(&self) -> RwLockReadGuard<'_, T, R> {
134            let Self(rw) = self;
135            rw.read()
136        }
137
138        /// Locks this rwlock with exclusive write access, blocking the current
139        /// thread until it can be acquired.
140        ///
141        /// # Panics
142        ///
143        /// This method may panic if the calling thread already holds the read
144        /// or write lock.
145        #[inline]
146        pub fn write(&self) -> RwLockWriteGuard<'_, T, R> {
147            let Self(rw) = self;
148            rw.write()
149        }
150
151        /// Consumes this rwlock, returning the underlying data.
152        #[inline]
153        pub fn into_inner(self) -> T {
154            let Self(rwlock) = self;
155            rwlock.into_inner()
156        }
157
158        /// Returns a mutable reference to the underlying data.
159        ///
160        /// Since this call borrows the [`RwLock`] mutably, no actual locking
161        /// needs to take place.
162        #[inline]
163        pub fn get_mut(&mut self) -> &mut T {
164            let Self(rwlock) = self;
165            rwlock.get_mut()
166        }
167    }
168}
169
170/// An alternative implementation that provides the exact same API for `Mutex`
171/// and `RwLock` as the `inner` module does, but alway`loom::sync` locks.
172#[cfg(loom)]
173mod inner_loom {
174    use core::fmt;
175    use core::marker::PhantomData;
176    use core::ops::{Deref, DerefMut};
177
178    use lock_api as _;
179
180    use crate::sync;
181
182    /// A mutex assuming lock poisoning will never occur.
183    pub struct Mutex<T, R>(sync::Mutex<T>, PhantomData<R>);
184
185    /// Lock guard for access to a [`Mutex`].
186    pub struct LockGuard<'a, T, R>(sync::MutexGuard<'a, T>, PhantomData<R>);
187
188    impl<T: fmt::Debug, R> fmt::Debug for LockGuard<'_, T, R> {
189        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190            let Self(g, _marker) = self;
191            g.fmt(f)
192        }
193    }
194
195    impl<T: fmt::Display, R> fmt::Display for LockGuard<'_, T, R> {
196        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197            let Self(g, _marker) = self;
198            g.fmt(f)
199        }
200    }
201
202    impl<T, R> Deref for LockGuard<'_, T, R> {
203        type Target = T;
204
205        fn deref(&self) -> &Self::Target {
206            let Self(g, _marker) = self;
207            g.deref()
208        }
209    }
210
211    impl<T, R> DerefMut for LockGuard<'_, T, R> {
212        fn deref_mut(&mut self) -> &mut Self::Target {
213            let Self(g, _marker) = self;
214            g.deref_mut()
215        }
216    }
217
218    impl<T: Default, R> Default for Mutex<T, R> {
219        #[inline]
220        fn default() -> Self {
221            Self::new(T::default())
222        }
223    }
224
225    impl<T: fmt::Debug, R> fmt::Debug for Mutex<T, R> {
226        #[inline]
227        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228            let Self(m, _marker) = self;
229            m.fmt(f)
230        }
231    }
232
233    impl<T, R> Mutex<T, R> {
234        /// Creates a new mutex in an unlocked state ready for use.
235        #[inline]
236        pub fn new(t: T) -> Self {
237            Self(sync::Mutex::new(t), PhantomData)
238        }
239
240        /// Acquires a mutex, blocking the current thread until it is able to do
241        /// so.
242        ///
243        /// # Panics
244        ///
245        /// This method may panic if the calling thread is already holding the
246        /// lock.
247        #[inline]
248        pub fn lock(&self) -> LockGuard<'_, T, R> {
249            let Self(m, _marker) = self;
250            LockGuard(m.lock().expect("unexpectedly poisoned"), PhantomData)
251        }
252
253        /// Consumes this mutex, returning the underlying data.
254        #[inline]
255        pub fn into_inner(self) -> T {
256            let Self(mutex, _marker) = self;
257            mutex.into_inner().expect("unexpectedly poisoned")
258        }
259    }
260
261    /// A reader-writer lock assuming lock poisoning will never occur.
262    pub struct RwLock<T, R>(sync::RwLock<T>, PhantomData<R>);
263
264    /// Lock guard for read access to a [`RwLock`].
265    pub struct RwLockReadGuard<'a, T, R>(sync::RwLockReadGuard<'a, T>, PhantomData<R>);
266
267    impl<T: fmt::Debug, R> fmt::Debug for RwLockReadGuard<'_, T, R> {
268        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269            let Self(g, _marker) = self;
270            g.fmt(f)
271        }
272    }
273
274    impl<T: fmt::Display, R> fmt::Display for RwLockReadGuard<'_, T, R> {
275        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276            let Self(g, _marker) = self;
277            g.fmt(f)
278        }
279    }
280
281    impl<T, R> Deref for RwLockReadGuard<'_, T, R> {
282        type Target = T;
283
284        fn deref(&self) -> &Self::Target {
285            let Self(g, _marker) = self;
286            g.deref()
287        }
288    }
289
290    /// Lock guard for write access to a [`RwLock`].
291    pub struct RwLockWriteGuard<'a, T, R>(sync::RwLockWriteGuard<'a, T>, PhantomData<R>);
292
293    impl<T: fmt::Debug, R> fmt::Debug for RwLockWriteGuard<'_, T, R> {
294        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295            let Self(g, _marker) = self;
296            g.fmt(f)
297        }
298    }
299
300    impl<T: fmt::Display, R> fmt::Display for RwLockWriteGuard<'_, T, R> {
301        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302            let Self(g, _marker) = self;
303            g.fmt(f)
304        }
305    }
306
307    impl<T, R> Deref for RwLockWriteGuard<'_, T, R> {
308        type Target = T;
309
310        fn deref(&self) -> &Self::Target {
311            let Self(g, _marker) = self;
312            g.deref()
313        }
314    }
315
316    impl<T, R> DerefMut for RwLockWriteGuard<'_, T, R> {
317        fn deref_mut(&mut self) -> &mut Self::Target {
318            let Self(g, _marker) = self;
319            g.deref_mut()
320        }
321    }
322
323    impl<T: Default, R> Default for RwLock<T, R> {
324        #[inline]
325        fn default() -> Self {
326            Self::new(T::default())
327        }
328    }
329
330    impl<T: fmt::Debug, R> fmt::Debug for RwLock<T, R> {
331        #[inline]
332        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333            let Self(rw, _marker) = self;
334            rw.fmt(f)
335        }
336    }
337
338    impl<T, R> RwLock<T, R> {
339        /// Creates a new instance of an `RwLock<T>` which is unlocked.
340        #[inline]
341        pub fn new(t: T) -> Self {
342            Self(sync::RwLock::new(t), PhantomData)
343        }
344
345        /// Locks this rwlock with shared read access, blocking the current
346        /// thread until it can be acquired.
347        ///
348        /// # Panics
349        ///
350        /// This method may panic if the calling thread already holds the read
351        /// or write lock.
352        #[inline]
353        pub fn read(&self) -> RwLockReadGuard<'_, T, R> {
354            let Self(rw, _marker) = self;
355            RwLockReadGuard(rw.read().expect("unexpectedly poisoned"), PhantomData)
356        }
357
358        /// Locks this rwlock with exclusive write access, blocking the current
359        /// thread until it can be acquired.
360        ///
361        /// # Panics
362        ///
363        /// This method may panic if the calling thread already holds the read
364        /// or write lock.
365        #[inline]
366        pub fn write(&self) -> RwLockWriteGuard<'_, T, R> {
367            let Self(rw, _marker) = self;
368            RwLockWriteGuard(rw.write().expect("unexpectedly poisoned"), PhantomData)
369        }
370
371        /// Consumes this rwlock, returning the underlying data.
372        #[inline]
373        pub fn into_inner(self) -> T {
374            let Self(rwlock, _marker) = self;
375            rwlock.into_inner().expect("unexpectedly poisoned")
376        }
377    }
378}
379
380impl<T: 'static, R: lock_api::RawMutex + 'static> lock_order::lock::ExclusiveLock<T>
381    for Mutex<T, R>
382{
383    type Guard<'l> = LockGuard<'l, T, R>;
384
385    fn lock(&self) -> Self::Guard<'_> {
386        self.lock()
387    }
388}
389
390impl<T, I: Ip, R> GenericOverIp<I> for Mutex<T, R>
391where
392    T: GenericOverIp<I>,
393{
394    type Type = Mutex<T::Type, R>;
395}
396
397impl<T: 'static, R: lock_api::RawRwLock + 'static> lock_order::lock::ReadWriteLock<T>
398    for RwLock<T, R>
399{
400    type ReadGuard<'l> = RwLockReadGuard<'l, T, R>;
401
402    type WriteGuard<'l> = RwLockWriteGuard<'l, T, R>;
403
404    fn read_lock(&self) -> Self::ReadGuard<'_> {
405        self.read()
406    }
407
408    fn write_lock(&self) -> Self::WriteGuard<'_> {
409        self.write()
410    }
411}
412
413impl<T, I: Ip, R> GenericOverIp<I> for RwLock<T, R>
414where
415    T: GenericOverIp<I>,
416{
417    type Type = RwLock<T::Type, R>;
418}