aboutsummaryrefslogtreecommitdiff
path: root/src/mutex.rs
blob: 0975b83c8a8e06f3a04a2e8ccc5f82588492764b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//! Implementation of a critical section based mutex that also implements the `mutex-trait`.
//!
//! ## Safety
//!
//! Note that this is only safe in single core applications.

use core::cell::UnsafeCell;

/// A critical section based mutex.
pub struct CriticalSectionMutex<T> {
    data: UnsafeCell<T>,
}

impl<T> CriticalSectionMutex<T> {
    /// Create a new mutex
    pub const fn new(data: T) -> Self {
        CriticalSectionMutex {
            data: UnsafeCell::new(data),
        }
    }
}

impl<T> mutex_trait::Mutex for &'_ CriticalSectionMutex<T> {
    type Data = T;

    fn lock<R>(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R {
        crate::interrupt::free(|_| f(unsafe { &mut *self.data.get() }))
    }
}

// NOTE A `Mutex` can be used as a channel so the protected data must be `Send`
// to prevent sending non-Sendable stuff (e.g. access tokens) across different
// execution contexts (e.g. interrupts)
unsafe impl<T> Sync for CriticalSectionMutex<T> where T: Send {}