Last active
December 25, 2019 07:46
-
-
Save cr1901/6e4761ab9e3debb9e9220093d25eb8c4 to your computer and use it in GitHub Desktop.
RefCell Misoptimization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "take-api" | |
version = "0.1.0" | |
authors = ["William D. Jones <[email protected]>"] | |
edition = "2018" | |
[dependencies] | |
bare-metal = {version = "0.2.5", optional = true } | |
[dependencies.msp430-rt] | |
git = "https://github.com/rust-embedded/msp430-rt" | |
branch = "rt-up" | |
version = "0.2.0" | |
[dependencies.panic-msp430] | |
version = "0.1.0" | |
[features] | |
bare_metal = ["bare-metal"] | |
# xargo build --manifest-path=take-api/Cargo.toml --release --target=msp430-none-elf [--features bare_metal] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![no_std] | |
#![no_main] | |
#![feature(lang_items, start)] | |
#![feature(abi_msp430_interrupt)] | |
extern crate panic_msp430; | |
use core::cell::UnsafeCell; | |
use core::cell::RefCell; | |
use msp430_rt::entry; | |
#[cfg(feature = "bare_metal")] | |
use bare_metal; | |
/// Critical section token | |
/// | |
/// Indicates that you are executing code within a critical section | |
pub struct CriticalSection { | |
_0: (), | |
} | |
impl CriticalSection { | |
/// Creates a critical section token | |
/// | |
/// This method is meant to be used to create safe abstractions rather than | |
/// meant to be directly used in applications. | |
pub unsafe fn new() -> Self { | |
CriticalSection { _0: () } | |
} | |
} | |
/// A "mutex" based on critical sections | |
/// | |
/// # Safety | |
/// | |
/// **This Mutex is only safe on single-core systems.** | |
/// | |
/// On multi-core systems, a `CriticalSection` **is not sufficient** to ensure exclusive access. | |
pub struct Mutex<T> { | |
inner: UnsafeCell<T>, | |
} | |
impl<T> Mutex<T> { | |
/// Creates a new mutex | |
pub const fn new(value: T) -> Self { | |
Mutex { | |
inner: UnsafeCell::new(value), | |
} | |
} | |
} | |
impl<T> Mutex<T> { | |
/// Borrows the data for the duration of the critical section | |
pub fn borrow<'cs>(&'cs self, _cs: &'cs CriticalSection) -> &'cs T { | |
unsafe { &*self.inner.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 Mutex<T> where T: Send {} | |
#[cfg(not(feature = "bare_metal"))] | |
static PERIPHERALS : Mutex<RefCell<Option<u8>>> = | |
Mutex::new(RefCell::new(None)); | |
#[cfg(feature = "bare_metal")] | |
static PERIPHERALS : bare_metal::Mutex<RefCell<Option<u8>>> = | |
bare_metal::Mutex::new(RefCell::new(None)); | |
#[entry] | |
fn main() -> ! { | |
#[cfg(not(feature = "bare_metal"))] | |
let _ = PERIPHERALS.borrow(unsafe { &CriticalSection::new() }).borrow_mut(); | |
#[cfg(not(feature = "bare_metal"))] | |
let _ = PERIPHERALS.borrow(unsafe { &CriticalSection::new() }).borrow(); | |
#[cfg(feature = "bare_metal")] | |
let _ = PERIPHERALS.borrow(unsafe { &bare_metal::CriticalSection::new() }).borrow_mut(); | |
#[cfg(feature = "bare_metal")] | |
let _ = PERIPHERALS.borrow(unsafe { &bare_metal::CriticalSection::new() }).borrow(); | |
loop { } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment