gpt4 book ai didi

rust - Rust 中的裸机自旋锁实现

转载 作者:行者123 更新时间:2023-12-05 05:57:28 36 4
gpt4 key购买 nike

我正在 64 位模式下运行的 Raspberry Pi 3 上使用 Rust 进行裸机编程。我已经实现了一个自旋锁,如下所示:

use core::{sync::atomic::{AtomicBool, Ordering}, cell::UnsafeCell, ops::{Deref, DerefMut}};

pub struct SpinMutex<T> {
lock: AtomicBool,
data: UnsafeCell<T>
}

impl<T> SpinMutex<T> {
#[allow(dead_code)]
pub const fn new(data: T) -> Self {
Self {
lock: AtomicBool::new(false),
data: UnsafeCell::new(data)
}
}

pub fn lock(&self) -> SpinMutexGuard<T> {
while self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() {}

SpinMutexGuard {
lock: &self.lock,
data: unsafe { &mut *self.data.get() }
}
}
}

unsafe impl<T> Sync for SpinMutex<T> {}

pub struct SpinMutexGuard<'a, T> {
lock: &'a AtomicBool,
data: &'a mut T
}

impl<'a, T> Deref for SpinMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}

impl<'a, T> DerefMut for SpinMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.data
}
}

impl<'a, T> Drop for SpinMutexGuard<'a, T> {
/// The dropping of the MutexGuard will release the lock it was created from.
fn drop(&mut self) {
self.lock.store(false, Ordering::Release);
}
}

#[cfg(test)]
mod tests {
use super::{SpinMutex};

#[test]
fn test_spin_mutex() {
let state = SpinMutex::new(0);

assert_eq!(*state.lock().data, 0);

*state.lock().data = 9;

assert_eq!(*state.lock().data, 9);
}
}

当我在我的本地机器(64 位 Windows)上运行测试时,锁起作用了。然而,在 Raspberry Pi 上,lock 方法陷入无限循环,永远不会返回。发生这种情况有原因吗?

这里是 Rust 如何在禁用内联的情况下编译 compare_exchange_weak:

   80ba8:   9100400a    add x10, x0, #0x10
80bac: 085f7d48 ldxrb w8, [x10]
80bb0: 34000068 cbz w8, 80bbc
80bb4: d5033f5f clrex
80bb8: 14000004 b 80bc8
80bbc: 52800029 mov w9, #0x1 // #1
80bc0: 080b7d49 stxrb w11, w9, [x10]
80bc4: 3400004b cbz w11, 80bcc
80bc8: 2a1f03e9 mov w9, wzr
80bcc: 7100011f cmp w8, #0x0
80bd0: 52000120 eor w0, w9, #0x1
80bd4: 1a9f07e1 cset w1, ne /

最佳答案

这是一个非详尽的条件列表,我确定(我已经对它们进行了两种测试)需要发生才能使原子在 EL1 (ARMv8) 中的 RPi 4 aarch64 上工作.这可能与 RPi 3 (ARMv7) 非常相似。

  • 必须启用 MMU(SCTLR_EL1 位 [0] 设置为 0b1)
  • 必须启用数据缓存(SCTLR_EL1 位 [2] 设置为 0b1)
  • 必须通过 MAIR 将锁所在的页面标记为正常的可缓存内存(我使用了 0xff - 我不确定哪些位是冗余 wrt.atomics,但我认为没有太多理由为正常内存使用其他任何东西)。

关于rust - Rust 中的裸机自旋锁实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68785276/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com