os/sync/
spin_lock.rs

1use core::cell::UnsafeCell;
2
3use crate::sync::raw_spin_lock::{RawSpinLock, RawSpinLockGuard};
4
5/// 提供对数据的互斥访问的自旋锁结构体。
6/// 内部包含一个 RawSpinLock 和一个 UnsafeCell 用于存储数据。
7/// 使用示例:
8/// ```ignore
9/// let lock = SpinLock::new(0);
10/// {
11///     let mut guard = lock.lock(); // 获取锁
12///     *guard += 1; // 访问和修改数据
13/// } // 离开作用域,自动释放锁
14/// ```
15/// 注意:SpinLock 不是可重入的。
16/// 当持有锁时,尝试再次获取锁将导致死锁。
17/// 确保在同一线程中不会嵌套调用 SpinLock::lock()。
18/// 此外,SpinLock 通过禁用中断来保护临界区,因此在持有锁时应避免长时间运行的操作,以防止影响系统响应性。
19#[derive(Debug)]
20pub struct SpinLock<T> {
21    raw_lock: RawSpinLock,
22    data: UnsafeCell<T>,
23}
24
25impl<T> SpinLock<T> {
26    /// 创建一个新的 SpinLock 实例,初始化内部数据。
27    pub const fn new(data: T) -> Self {
28        SpinLock {
29            raw_lock: RawSpinLock::new(),
30            data: UnsafeCell::new(data),
31        }
32    }
33
34    /// 获取自旋锁,并返回一个 RAII 保护器,用于访问和修改内部数据。
35    pub fn lock(&self) -> SpinLockGuard<'_, T> {
36        let _raw_guard = self.raw_lock.lock();
37        SpinLockGuard {
38            _raw_guard,
39            data: unsafe { &mut *self.data.get() },
40        }
41    }
42
43    /// 尝试获取自旋锁,如果成功则返回 RAII 保护器,否则返回 None。
44    pub fn try_lock(&self) -> Option<SpinLockGuard<'_, T>> {
45        self.raw_lock.try_lock().map(|_raw_guard| SpinLockGuard {
46            _raw_guard,
47            data: unsafe { &mut *self.data.get() },
48        })
49    }
50
51    /// 检查锁是否被占用 (仅用于调试/测试)
52    /// 返回值:锁是否被占用
53    #[cfg(test)]
54    pub fn is_locked(&self) -> bool {
55        self.raw_lock.is_locked()
56    }
57}
58
59/// SpinLock 的 RAII 保护器,提供对锁定数据的访问。
60/// 当保护器离开作用域时,自动释放锁。
61pub struct SpinLockGuard<'a, T> {
62    _raw_guard: RawSpinLockGuard<'a>,
63    data: &'a mut T,
64}
65
66impl<T> core::ops::Deref for SpinLockGuard<'_, T> {
67    type Target = T;
68
69    fn deref(&self) -> &Self::Target {
70        self.data
71    }
72}
73
74impl<T> core::ops::DerefMut for SpinLockGuard<'_, T> {
75    fn deref_mut(&mut self) -> &mut Self::Target {
76        self.data
77    }
78}
79
80// Safety: SpinLock 可以在线程间安全共享,
81// 因为它通过 RawSpinLock 保证了对数据的互斥访问。
82unsafe impl<T: Send> Send for SpinLock<T> {}
83unsafe impl<T: Send> Sync for SpinLock<T> {}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88    use crate::{kassert, println, test_case};
89
90    // 基本功能:获取锁、修改数据、释放后检查值与锁状态
91    test_case!(test_spinlock_basic, {
92        println!("Testing: test_spinlock_basic");
93        let lock = SpinLock::new(0usize);
94
95        // 初始应未锁定
96        kassert!(!lock.is_locked());
97
98        // 获取锁并修改数据
99        {
100            let mut guard = lock.lock();
101            kassert!(lock.is_locked());
102            *guard = 42;
103            kassert!(*guard == 42);
104        } // guard 离开作用域,释放锁
105
106        // 释放后应恢复为未锁定
107        kassert!(!lock.is_locked());
108    });
109
110    // 检查释放后能再次加锁(避免在同一线程内重入)
111    test_case!(test_spinlock_relock_after_drop, {
112        println!("Testing: test_spinlock_relock_after_drop");
113        let lock = SpinLock::new(1usize);
114
115        {
116            let mut g1 = lock.lock();
117            *g1 += 1;
118            kassert!(*g1 == 2);
119            // g1 在此作用域结束并释放锁
120        }
121
122        // 释放后,应该能再次获取锁
123        {
124            let mut g2 = lock.lock();
125            *g2 += 1;
126            kassert!(*g2 == 3);
127        }
128        kassert!(!lock.is_locked());
129    });
130}