Comment

Comment by blippage

I'm not a Rust programmer, so be gentle with me.

What worries me is that when it comes to safety, surely the chain is as strong as the weakest link? You declare one thing unsafe, and then suddenly all bets are off. And maybe you don't even know that what you're doing is unsafe.

But here's an example I pulled from github, which blinks a Raspberry Pi Pico:

    // Set GPIO25 to be an output (output enable is set)
    p.SIO.gpio_oe_set.write(|w| unsafe {
        w.bits(1 << 25);
        w
    });
Right, but what if you're fiddling with registers that might require atomic operations? Lines such as this seem to be saying "ignore all that, write to the register anyway."

Fearless concurrency, you say: are you sure? How do you know?

Suppose you have an ISR (interrupt service routine) that wants to toggle a GPIO pin. From whence does it borrow the privilege to set the pin?

Surely, at the end of the day, microcontrollers can be characterised as large state machines with global state. That's what they ARE. It's their inherent nature, which you cannot abstract away without it leaking somewhere (at least to do anything useful, anyway).

At least with C/C++ you KNOW you've got a problem, and have to reason about the problem carefully. With Rust, you THINK you've solved the problem, but have you?

"Change My View", as they say on Reddit.

*Update 1* OK, I'm going to press my point on this. I'm looking at the Embedded Rust Book (please remember, I'm not a Rust programmer) at https://docs.rust-embedded.org/book/concurrency/index.html

I'm considering the issue of interrupts here.

" Instead, our interrupt handlers might be called at any time and must know how to access whatever shared memory we are using. At the lowest level, this means we must have statically allocated mutable memory, which both the interrupt handler and the main code can refer to."

"In Rust, such static mut variables are always unsafe to read or write, because without taking special care, you might trigger a race condition, where your access to the variable is interrupted halfway through by an interrupt which also accesses that variable."

RIGHT, but that means that Rust gives me no better assurances than C/C++. Here's their code:

    static mut COUNTER: u32 = 0;
    
    #[entry]
    fn main() -> ! {
        set_timer_1hz();
        let mut last_state = false;
        loop {
            let state = read_signal_level();
            if state && !last_state {
                // DANGER - Not actually safe! Could cause data races.
                unsafe { COUNTER += 1 };
            }
            last_state = state;
        }
    }
    
    #[interrupt]
    fn timer() {
        unsafe { COUNTER = 0; }
    }
Then is says "Can you spot the race condition? The increment on COUNTER is not guaranteed to be atomic"

It then solves the problem by showing how to introduce a critical section.

So at the end of the day it's just C with different syntax, and a lot more hoopla. You've made everything mutable and unsafe. Exactly the kind of thing you were trying to avoid in the first place.

parent blippage 5 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton