编译器如何优化对`static mut`的读/写?

问题描述 投票:0回答:1

我编写的代码有点像这样:

#![no_std]

static mut DATA: usize = 0;

#[no_mangle]
pub unsafe fn update() {
    DATA = 1;
}

#[no_mangle]
pub unsafe fn wait_for_data() {
    while DATA == 0 {}
    DATA = 1;
}

在我的例子中,

update
函数由硬件中断调用,并且
wait_for_data
在主程序中运行。因此,我们可以假设
DATA
while
循环期间会发生变化。我假设
static mut
会告诉编译器该地址可以在多个并发执行线程之间共享。但是,编译器会通过在第一次迭代时跳转到无限循环 if
DATA == 0
来优化此代码。

现在我的问题是:

  • 编译器是否假设不会发生对
    DATA
    的并发访问?
  • 此用例是否需要易失性读/写或原子?
rust llvm compiler-optimization
1个回答
0
投票

问题是,你告诉编译器你知道你在做什么(

wait_for_data
unsafe
)。但是使用
PartialEq
(通过
==
)意味着
wait_for_data
需要共享对
DATA
的引用(签名是
fn eq(&self, other: &Rhs) -> bool;
),所以你保证,不存在对
DATA
的 mutalbe 引用,因为那将是UB 每:

  • 打破指针别名规则。 Box、&mut T 和 &T 遵循 LLVM 的作用域 noalias 模型,除非 &T 包含 UnsafeCell。参考文献和盒子在使用时不得悬挂。确切的活跃持续时间没有指定,但存在一些界限:

    • 作为参考,活跃持续时间的上限由借用检查器分配的语法生命周期决定;它的寿命不能超过该寿命。
    • 每次将引用或框传递给函数或从函数返回时,它都被视为活动。
    • 当引用(但不是 Box!)传递给函数时,它至少与该函数调用一样长,除非 &T 包含 UnsafeCell。

    当这些类型的值在复合类型的(嵌套)字段中传递时,所有这些也适用,但不在指针间接后面传递。

因此编译器可以安全地假设

DATA
不会改变,并优化循环。

© www.soinside.com 2019 - 2024. All rights reserved.