-
-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Safety, races, and interrupts #26
Comments
In my latest tinkering with GBA stuff, I use a type called GbaCell, which is technically unsound, and it happens to be the case that for simple programs the compiler can't bite me in the butt (yet). To quote LLVM's Memory Model for Concurrent Operations again:
So, volatile accesses short-circuit the normal data race rules (good), and just "do what the hardware does" (okay), but even in a single-threaded situation you can't ensure that volatile and standard accesses stay properly ordered (very bad), Now, at this point you might say "oh we'll use a The problem with using atomics is that until recently the atomic types didn't actually work on older systems without literal atomic instructions. There's hope though! With rust-lang/rust#100621 we'll be able to declare atomic values (8, 16, and 32 bit) and use atomic load/store (but not the more advanced atomic methods), and these will, when used properly, give correct ordering guarantees. This will finally let us have global mutable data in a sound way on older devices. But we do have to wait for that PR to roll out, and I'm not sure if there will be other steps after that for it to get into a usable state. |
PS: I'm told that LLVM allows an access to be atomic and volatile at the same time, but rust does not expose this even on nightly. |
Thanks for your responses, really useful info.
Yeah, I've been doing some reading and discovered the same. I should try and figure out the best place to raise this with the standard library team as it seems like a generically valuable feature to support. My personal approach to safe It's a shame because I'd love to be able to use Rust's guarantees, rather than having to dig through what the LLVM backend implements. After some more reading, my current thinking is that |
Procedurally: new intrinsics, ones that express new things you couldn't before, are T-lang first. Then T-libs-api eventually gets to pick how it's exposed stably to users once the intrinsic seems to be doing stuff as expected. |
But yes, all mmio is basically device specific, so "this works on the exact device I'll use it with" is what you're promising. |
What I eventually implemented for GbaCell is just giving up and using inline assembly, so that LLVM has to assume that I might have used atomic synchronization and such and just do what I say without being able to reorder anything across the asm blocks. I think that's really the best that can be done for now. I'm going to close this issue, since there's not really anything more that can be done by this crate. Further advancements in this area hinges on language developments, not something I can fix. |
This is related to #15
As I see it, there are two problems with the common idea of using a
static mut _: Cell
for MMIO. As well documented here one of these is ensuring that access is properly volatile and non-dereferencable. As far as I can see, this crate solves that.However, there are other problems with
static mut _: Cell
, even if you're not using it for volatile access (including MMIO). The documentation currently sayswhich suggests to me that there are cases where using
VolAddress
through a globalconst
is sound. But I don't think that's the case. The obvious case is where the target has multiple hardware threads. However, I think that interrupts are another source of data races, even on single-core microcontrollers. It may be the case that the compiler produces access instructions that are atomic in some cases, but this is not guaranteed.I honestly don't know how this can be solved, so I'm mostly opening this issue as a brainstorm. For non-volatile access, you can use atomics with
Ordering::Relaxed
, safe in the knowledge that it's zero-overhead for most common architectures. But I don't think it's possible to mark an access as both volatile and atomic simultaneously?The text was updated successfully, but these errors were encountered: