Comments (10)
This is AtomicUsize
from bare-metal.
Here is a real example with your code https://godbolt.org/z/GsYx1q
you can see that
// Wait for the flag
while FOO.get() == 0 {
// nop
}
is compiled to
// Wait for the flag
if FOO.get() == 0 {
loop {
// nop
}
}
Compiler assumes there is no data races in the code, so value of FOO can never change inside the loop. Which means no need to read it every time we can check it only once.
from bare-metal.
This exact problem actually can occur with the bare-metal Mutex, which is why we added documentation in #34 after discussion in #33 (comment). In the cortex-m crate, compiler fences or memory clobbers are used when entering and leaving critical sections to ensure the compiler does not move accesses outside the the critical section, as otherwise @pftbest's example above would miscompile the same way.
from bare-metal.
This is
AtomicUsize
But is this available on all single-core platforms, e.g. Cortex M0? I thought it wasn't (https://rust-embedded.github.io/book/concurrency/index.html#atomic-access). Also if it does synchronization across cores, it's not exactly the same thing as I'm proposing: atomics across interrupts on the same core, with no cross-core synchronization overhead.
from bare-metal.
The atomic types are available everywhere (if not, that's a bug in Rust or LLVM), but CAS operations might not be. load
and store
are always available.
You still need to synchronize access between interrupt handlers and idle. As written, SingleCoreAtomicUsize
causes data races between every get and set, which is undefined behavior.
from bare-metal.
The atomic types are available everywhere (if not, that's a bug in Rust or LLVM), but CAS operations might not be.
load
andstore
are always available.
Thanks, I will double check this.
You still need to synchronize access between interrupt handlers and idle. As written,
SingleCoreAtomicUsize
causes data races between every get and set, which is undefined behavior.
I don't understand what data race you're talking about. Could you give an example of a scenario where the data race would trigger, and how it's UB?
Also, I'm unsure how I can get AtomicUsize
to have the behaviour I was looking for: for platforms that do support multi-core (e.g your typical computer), how would you trigger a no-cross-core-synchronization read or write from an AtomicUsize
? Just using Ordering::Relaxed
?
from bare-metal.
The unsafe impl Sync
allows use of SingleCoreAtomicUsize
across threads, but there is no inner synchronization, so any usage of get or set from more than one thread would be a data race, as the stores and loads happen unsynchronized with each other.
This is still the case if you replace "thread" with "interrupt handler". For example, the compiler might assume that a value loaded by subsequent get
s stays the same if there is no set
inbetween. This is wrong in the presence of interrupts.
The Relaxed
ordering is all you need as long as you only need to synchronize accesses of the AtomicUsize
itself, not any other data (the other orderings are used when writing lock free data structures with atomics, and affect how the compiler synchronizes non-atomic accesses to the actual data stored in the data structure).
from bare-metal.
Thanks a lot for the explanation 👍 I think I understood almost all of it now! :)
The compiler might assume that a value loaded by subsequent
get
s stays the same if there is noset
inbetween. This is wrong in the presence of interrupts.
From the UnsafeCell documentation:
UnsafeCell is a type that wraps some T and indicates unsafe interior operations on the wrapped type. Types with an UnsafeCell field are considered to have an 'unsafe interior'.
The compiler makes optimizations based on the knowledge that &T is not mutably aliased or mutated, and that &mut T is unique. UnsafeCell is the only core language feature to work around the restriction that &T may not be mutated.
I thought this explained it prevented that kind of optimizations.and enforced actually re-reading the value everytime it's asked.
Does it actually only force re-read if the compiler detects it might have changed due to some mutable aliasing, but in the same execution flow?
from bare-metal.
That was just an example of an assumption that a compiler might make. You'd have to ask that question in terms of Rust's language semantics to get a complete answer, and I'm not sure how the precise answer looks there.
from bare-metal.
Great, thank you for all the examples and references!
Closing this as it's already in core
.
from bare-metal.
Related Issues (11)
- Beta / 2018 Edition compatibility complications HOT 2
- Mutex is not safe on multi-core systems HOT 24
- Mutex.borrow_mut() HOT 8
- Move to EWG HOT 1
- Ship a 1.0 release HOT 8
- Pre-1.0 API Guidelines Audit HOT 3
- Should `CriticalSection` really be `Clone` ? HOT 14
- Add inherent `impl` blocks for `Mutex<RefCell<T>>`? HOT 1
- Soundness issue in the Mutex API
- Inefficiency in the CriticalSection API
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bare-metal.