-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Rust inline assembly with static mutable #140059
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
Comments
Other version #[unsafe(no_mangle)]
#[used]
pub static mut flag: bool = false;
fn set_flag(flag_ptr: *mut bool) {
unsafe {
asm!(
"strb {}, [{}]", in(reg) 1, in(reg) flag_ptr) ;
}
}
#[unsafe(no_mangle)]
pub fn start() {
set_flag(&raw mut flag);
unsafe {
while flag == false {
}
}
} LL
LLC
|
When calling a function using The following code works on my machine. #[unsafe(no_mangle)]
#[used]
pub static mut FLAG: bool = false;
extern "C" fn set_flag() {
unsafe {
FLAG = true;
}
}
fn set_callback() {
unsafe {
core::arch::asm!("bl {}", sym set_flag, clobber_abi("C"));
}
}
fn main() {
set_callback();
unsafe { while FLAG == false {} }
} |
The problem here is because this introduces a data race. Part of the reason |
@rustbot label -C-bug -needs-triage +C-discussion +T-compiler |
@asquared31415
how do I tell the compiler that data races do happen then? Is it something that interior mutability solves? I tried using SyncUnsafeCell here and it still produces the same output. Is it because there's nothing on |
Why it's not expected? cmp r0, #0
popne {r11, lr}
bxne lr
b 0x20134 It's just bool test = FLAG != 0;
if (test) {
return;
}
while (true) {} optimized from bool test = FLAG != 0;
if (test) {
return;
}
while (!test) {} optimized from if (!(FLAG == 0)) {
return;
}
while (FLAG == 0) {} optimized from while (FLAG == 0) {}
return; |
@usamoi it's not expected because I wrote while flag == false { } so I expect Perhaps my original code was not clear. The whole fn set_callback() {
unsafe {
core::arch::asm!("register TIMER_0's interrupt handler to address: {}", sym set_flag, clobber_abi("C"));
}
} instead of simply calling a function by using |
This has nothing to do with asm blocks; as long as you're still reading from or writing to
See https://doc.rust-lang.org/std/sync/atomic/fn.compiler_fence.html. |
@usamoi However trying to use one in my code results in linking error...
|
I believe this is a real bug. Please open another issue for this. If the target is an embedded platform, you can define this symbol manually. #[unsafe(no_mangle)]
extern "C" fn __sync_synchronize() {} |
Thank you everyone I think it is expected behavior then, I'll read more about fences. As for the issue, let's discuss further in #140105 |
Overview: I think Rust is optimizing away checks to reading from a static mut variable that is modified in inline assembly.
I tried this code:
I expected to see this happen: I have a program that loops to check if flag is false, and I expect it to break when it becomes true. The flag is set by a function that's referenced by inline assembly.
Instead, this happened: The program stuck on infinite loop, without checking the flag variable.
Currently, my only workaround is this:
which of course works, but I'm curious if this is indeed a bug or if I'm using Rust wrong.
Meta
rustc --version --verbose
:Note: I realized I was using outdated nightly build so I tried updating but I still have the same issue with
rustc --version --verbose
:I'm targetting armv4t-none-eabi, this is a no_std, build-std=["core"] setup.
LLC from Godbolt
LL
The text was updated successfully, but these errors were encountered: