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
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! Core abstractions of the Real Time For the Masses (RTFM) framework
//!
//! You can write generic *libraries* by using the `Resource` trait in this
//! crate. If you want to write application code then you'll need an
//! implementation of the RTFM framework for a particular architecture.
//! Currently there are implementations for these two architectures:
//!
//! - [ARM Cortex-M](https://github.com/japaric/cortex-m-rtfm)
//! - [MSP430](https://github.com/japaric/msp430-rtfm)
#![deny(missing_docs)]
#![deny(warnings)]
#![feature(optin_builtin_traits)]
#![no_std]

extern crate static_ref;

use core::u8;

pub use static_ref::Static;

/// A resource, a mechanism to share data between tasks
pub unsafe trait Resource {
    /// The data protected by the resource
    type Data: Send;

    /// Borrows the resource data for the duration of a critical section
    ///
    /// # Panics
    ///
    /// This will `panic!` if the threshold is not high enough to protect the
    /// resource data from data races
    fn borrow<'cs>(&'cs self, t: &'cs Threshold) -> &'cs Static<Self::Data>;

    /// Mutable variant of `borrow`
    fn borrow_mut<'cs>(
        &'cs mut self,
        t: &'cs Threshold,
    ) -> &'cs mut Static<Self::Data>;

    /// Claims the resource data for the span of the closure `f`. For the
    /// duration of the closure other tasks that may access the resource data
    /// are prevented from preempting the current task.
    fn claim<R, F>(&self, t: &mut Threshold, f: F) -> R
    where
        F: FnOnce(&Static<Self::Data>, &mut Threshold) -> R;

    /// Mutable variant of `claim`
    fn claim_mut<R, F>(&mut self, t: &mut Threshold, f: F) -> R
    where
        F: FnOnce(&mut Static<Self::Data>, &mut Threshold) -> R;
}

unsafe impl<T> Resource for Static<T>
where
    T: Send,
{
    type Data = T;

    fn borrow<'cs>(&'cs self, _cs: &'cs Threshold) -> &'cs Static<T> {
        self
    }

    fn borrow_mut<'cs>(
        &'cs mut self,
        _cs: &'cs Threshold,
    ) -> &'cs mut Static<T> {
        self
    }

    fn claim<R, F>(&self, t: &mut Threshold, f: F) -> R
    where
        F: FnOnce(&Static<Self::Data>, &mut Threshold) -> R,
    {
        f(self, t)
    }

    fn claim_mut<R, F>(&mut self, t: &mut Threshold, f: F) -> R
    where
        F: FnOnce(&mut Static<Self::Data>, &mut Threshold) -> R,
    {
        f(self, t)
    }
}

/// Preemption threshold token
///
/// The preemption threshold indicates the priority a task must have to preempt
/// the current context. For example a threshold of 2 indicates that only
/// interrupts / exceptions with a priority of 3 or greater can preempt the
/// current context
pub struct Threshold {
    value: u8,
}

impl Threshold {
    /// Creates a new `Threshold` token
    ///
    /// This API is meant to be used to create abstractions and not to be
    /// directly used by applications.
    pub unsafe fn new(value: u8) -> Self {
        Threshold { value }
    }

    /// Creates a `Threshold` token with maximum value
    ///
    /// This API is meant to be used to create abstractions and not to be
    /// directly used by applications.
    pub unsafe fn max() -> Self {
        Self::new(u8::MAX)
    }

    /// Returns the value of this `Threshold` token
    pub fn value(&self) -> u8 {
        self.value
    }
}

impl !Send for Threshold {}