rust-embedded / bare-metal

Abstractions common to microcontrollers
Apache License 2.0
116 stars 17 forks source link

Add borrow_mut function to Mutex #8

Closed yodaldevoid closed 6 years ago

yodaldevoid commented 6 years ago

I have encountered points where I would like a mutable reference from a Mutex and have chafed at the lack of a way of getting one. I have in the past placed a RefCell inside the Mutex to get around this, but this is just placing on UnsafeCell needlessly inside another. This PR simply adds a borrow_mut function to fill this hole in the API.

yodaldevoid commented 6 years ago

@japaric Pinging to make sure this didn't get lost in the shuffle.

japaric commented 6 years ago

This is unsound for the reasons given in https://github.com/rust-lang-nursery/embedded-wg/issues/113#issuecomment-403118015.

but this is just placing on UnsafeCell needlessly inside another.

It's not doing just that RefCell also keeps count of the number of immutable or mutable borrows that exist. That's required for safety: a RefCell will panic if you try to get two &mut from it; your proposed API will hand over as many &mut references as you ask for and that breaks Rust aliasing rules:

static M: Mutex<u32> = Mutex::new(0);

fn alias(cs: &CriticalSection) {
    let y: &mut u32 = M.borrow_mut(cs);
    let aliased_y: &mut u32 = M.borrow_mut(cs);
} 
yodaldevoid commented 6 years ago

Thank you for pointing out the unsoudness of this.

I suppose I had not thought about the problems as I was only considering my specific case and not the general one. The specific case being an environment with only one thread, so stopping interrupts prevents the possibility of two pieces of code trying to get a mutable reference at the same time.