Skip to main content

sparreal_kernel/os/sync/
spinlock.rs

1//! 禁止中断的Spinlock实现
2//!
3//! 提供中断安全的互斥锁,在持有锁期间会自动禁用中断。
4//! 适用于保护临界区,防止中断处理程序与主线程之间的竞争条件。
5
6use core::cell::UnsafeCell;
7use core::ops::{Deref, DerefMut};
8use core::sync::atomic::{AtomicBool, Ordering};
9
10use crate::os::irq::NoIrqGuard;
11
12/// 禁止中断的原始Spinlock实现
13///
14/// 使用原子操作和中断禁用来提供线程安全。
15/// 在获取锁时会禁用中断,释放锁时恢复中断状态。
16pub struct IrqRawSpinlock {
17    locked: AtomicBool,
18}
19
20impl IrqRawSpinlock {
21    /// 创建一个新的IrqRawSpinlock实例
22    #[inline]
23    pub const fn new() -> Self {
24        Self {
25            locked: AtomicBool::new(false),
26        }
27    }
28}
29
30impl Default for IrqRawSpinlock {
31    #[inline]
32    fn default() -> Self {
33        Self::new()
34    }
35}
36
37impl IrqRawSpinlock {
38    /// 获取锁(阻塞直到获取成功)
39    ///
40    /// 纯粹的锁获取操作,不涉及中断管理。
41    /// 中断管理应该在调用层面处理。
42    #[inline]
43    pub fn lock(&self) {
44        // 自旋获取锁,使用退避策略优化性能
45        let mut spin_count = 0;
46
47        while self
48            .locked
49            .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
50            .is_err()
51        {
52            // 提示CPU我们正在自旋等待
53            core::hint::spin_loop();
54
55            // 简单的退避策略:避免CPU过度占用
56            spin_count = (spin_count + 1) & 0xFFF;
57            if spin_count == 0 {
58                // 每自旋4096次,给CPU一点休息时间
59                core::hint::spin_loop();
60            }
61        }
62    }
63
64    /// 尝试获取锁(非阻塞)
65    ///
66    /// 纯粹的锁获取尝试,不涉及中断管理。
67    ///
68    /// # Returns
69    ///
70    /// * `true` - 成功获取锁
71    /// * `false` - 锁已被占用
72    #[inline]
73    pub fn try_lock(&self) -> bool {
74        // 尝试获取锁
75        self.locked
76            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
77            .is_ok()
78    }
79
80    /// 释放锁
81    ///
82    /// 此方法会恢复中断状态(如果通过lock获取的)。
83    ///
84    /// # Safety
85    ///
86    /// 调用者必须确保当前线程持有该锁。
87    #[inline]
88    pub unsafe fn unlock(&self) {
89        self.locked.store(false, Ordering::Release);
90    }
91
92    /// 检查锁是否被占用
93    #[inline]
94    pub fn is_locked(&self) -> bool {
95        self.locked.load(Ordering::Acquire)
96    }
97}
98
99/// 中断安全的互斥锁
100///
101/// 在持有锁期间会自动禁用中断,适用于内核临界区保护。
102pub struct IrqSpinlock<T> {
103    raw: IrqRawSpinlock,
104    data: UnsafeCell<T>,
105    // PhantomData不再需要,因为UnsafeCell已经提供了正确的不变性
106}
107
108// IrqSpinlock是Send(如果T是Send)
109unsafe impl<T: Send> Send for IrqSpinlock<T> {}
110
111// IrqSpinlock是Sync(如果T是Send)
112unsafe impl<T: Send> Sync for IrqSpinlock<T> {}
113
114/// IrqSpinlock的锁守卫
115///
116/// 当这个守卫被drop时,锁会自动释放,中断状态也会恢复。
117pub struct IrqMutexGuard<'a, T> {
118    lock: &'a IrqSpinlock<T>,
119    _irq_guard: NoIrqGuard, // 确保中断在整个守卫生命周期内被禁用
120}
121
122impl<T> IrqSpinlock<T> {
123    /// 创建一个新的IrqSpinlock实例
124    ///
125    /// # Arguments
126    ///
127    /// * `data` - 要保护的数据
128    ///
129    /// # Returns
130    ///
131    /// 返回一个包含指定数据的IrqSpinlock实例
132    ///
133    /// # Examples
134    ///
135    /// ```
136    /// use sparreal_kernel::os::sync::spinlock::IrqSpinlock;
137    ///
138    /// let lock = IrqSpinlock::new(42);
139    /// ```
140    #[inline]
141    pub const fn new(data: T) -> Self {
142        Self {
143            raw: IrqRawSpinlock::new(),
144            data: UnsafeCell::new(data),
145        }
146    }
147
148    /// 创建一个空的IrqSpinlock
149    #[inline]
150    pub const fn empty() -> IrqSpinlock<()> {
151        IrqSpinlock::new(())
152    }
153
154    /// 获取锁,如果锁被占用则自旋等待
155    ///
156    /// 调用此方法会禁用中断,直到返回的守卫被drop。
157    ///
158    /// # Returns
159    ///
160    /// 返回一个守卫,通过它可以访问受保护的数据
161    ///
162    /// # Safety
163    ///
164    /// 在持有锁期间,中断会被禁用,因此调用者需要确保:
165    /// 1. 尽快释放锁
166    /// 2. 不要在持有锁期间执行可能长时间阻塞的操作
167    /// 3. 避免嵌套获取同一个锁
168    #[inline]
169    pub fn lock(&self) -> IrqMutexGuard<'_, T> {
170        for _ in 0..100 {
171            if let Some(guard) = self.try_lock() {
172                return guard;
173            }
174        }
175        panic!("IrqSpinlock lock timeout");
176    }
177
178    /// 尝试获取锁,如果失败则立即返回
179    ///
180    /// 这个方法不会自旋等待,而是立即返回结果。
181    /// 如果成功获取锁,中断也会被禁用,直到守卫被drop。
182    ///
183    /// # Returns
184    ///
185    /// * `Some(guard)` - 成功获取锁时的守卫,中断已禁用
186    /// * `None` - 锁已被占用时,中断状态不变
187    #[inline]
188    pub fn try_lock(&self) -> Option<IrqMutexGuard<'_, T>> {
189        let irq_guard = NoIrqGuard::new();
190        if self.raw.try_lock() {
191            Some(IrqMutexGuard::new(self, irq_guard))
192        } else {
193            None
194        }
195    }
196
197    /// 检查锁是否被占用
198    ///
199    /// # Returns
200    ///
201    /// * `true` - 锁被占用
202    /// * `false` - 锁空闲
203    #[inline]
204    pub fn is_locked(&self) -> bool {
205        self.raw.is_locked()
206    }
207
208    /// 获取内部数据的不可变引用
209    ///
210    /// # Safety
211    ///
212    /// 此方法不提供同步保证,调用者需要确保没有其他地方在并发访问数据
213    #[inline]
214    pub unsafe fn get(&self) -> *mut T {
215        self.data.get()
216    }
217
218    /// 获取内部数据的可变引用
219    ///
220    /// # Safety
221    ///
222    /// 此方法不提供同步保证,调用者需要确保没有其他地方在并发访问数据
223    #[inline]
224    pub unsafe fn get_mut(&mut self) -> &mut T {
225        unsafe { &mut *self.data.get() }
226    }
227
228    /// 消费IrqSpinlock并返回内部数据
229    ///
230    /// # Returns
231    ///
232    /// 返回受保护的数据
233    #[inline]
234    pub fn into_inner(self) -> T {
235        self.data.into_inner()
236    }
237
238    /// 获取锁但不使用RAII守卫(高级用法)
239    ///
240    /// # Safety
241    ///
242    /// 调用者必须确保:
243    /// 1. 手动管理中断禁用
244    /// 2. 在适当的时机调用unlock
245    /// 3. 不会发生死锁或竞态条件
246    #[inline]
247    pub unsafe fn lock_raw(&self) -> &IrqRawSpinlock {
248        &self.raw
249    }
250}
251
252impl<'a, T> IrqMutexGuard<'a, T> {
253    fn new(lock: &'a IrqSpinlock<T>, irq_guard: NoIrqGuard) -> Self {
254        Self {
255            lock,
256            _irq_guard: irq_guard,
257        }
258    }
259}
260
261impl<T> Drop for IrqMutexGuard<'_, T> {
262    #[inline]
263    fn drop(&mut self) {
264        unsafe {
265            self.lock.raw.unlock();
266        }
267    }
268}
269
270impl<T> Deref for IrqMutexGuard<'_, T> {
271    type Target = T;
272
273    #[inline]
274    fn deref(&self) -> &Self::Target {
275        unsafe { &*self.lock.data.get() }
276    }
277}
278
279impl<T> DerefMut for IrqMutexGuard<'_, T> {
280    #[inline]
281    fn deref_mut(&mut self) -> &mut Self::Target {
282        unsafe { &mut *self.lock.data.get() }
283    }
284}
285
286#[cfg(test)]
287mod tests {
288    use super::*;
289    use crate::alloc::string::String;
290
291    #[test]
292    fn test_irq_raw_spinlock_creation() {
293        let spinlock = IrqRawSpinlock::new();
294        assert!(!spinlock.is_locked());
295    }
296
297    #[test]
298    fn test_irq_raw_spinlock_default() {
299        let spinlock = IrqRawSpinlock::default();
300        assert!(!spinlock.is_locked());
301    }
302
303    #[test]
304    fn test_irq_raw_spinlock_try_lock() {
305        let spinlock = IrqRawSpinlock::new();
306
307        // 首次尝试获取锁应该成功
308        assert!(spinlock.try_lock());
309        assert!(spinlock.is_locked());
310
311        // 第二次尝试获取锁应该失败
312        assert!(!spinlock.try_lock());
313
314        // 释放锁
315        unsafe {
316            spinlock.unlock();
317        }
318        assert!(!spinlock.is_locked());
319
320        // 再次尝试获取锁应该成功
321        assert!(spinlock.try_lock());
322        unsafe {
323            spinlock.unlock();
324        }
325    }
326
327    #[test]
328    fn test_irq_spinlock_creation() {
329        let lock = IrqSpinlock::new(42);
330        assert!(!lock.is_locked());
331
332        // 测试into_inner
333        let value = lock.into_inner();
334        assert_eq!(value, 42);
335    }
336
337    #[test]
338    fn test_irq_spinlock_empty() {
339        let lock: IrqSpinlock<()> = IrqSpinlock::<()>::empty();
340        assert!(!lock.is_locked());
341
342        let value: () = lock.into_inner();
343        assert_eq!(value, ());
344    }
345
346    #[test]
347    fn test_irq_spinlock_try_lock() {
348        let lock = IrqSpinlock::new(42);
349
350        // 首次尝试获取锁应该成功
351        {
352            let guard = lock.try_lock().unwrap();
353            assert_eq!(*guard, 42);
354            assert!(lock.is_locked());
355        } // guard被drop,锁被释放
356
357        assert!(!lock.is_locked());
358
359        // 再次尝试获取锁应该成功
360        {
361            let guard = lock.try_lock().unwrap();
362            assert_eq!(*guard, 42);
363        }
364    }
365
366    #[test]
367    fn test_irq_spinlock_try_lock_failure() {
368        let lock = IrqSpinlock::new(42);
369
370        // 获取锁
371        let guard1 = lock.try_lock().unwrap();
372        assert!(lock.is_locked());
373
374        // 第二次尝试获取锁应该失败
375        let guard2 = lock.try_lock();
376        assert!(guard2.is_none());
377
378        // 释放第一个锁
379        drop(guard1);
380        assert!(!lock.is_locked());
381    }
382
383    #[test]
384    fn test_irq_spinlock_lock_and_modify() {
385        let lock = IrqSpinlock::new(0);
386
387        {
388            let mut guard = lock.lock();
389            *guard = 100;
390            assert_eq!(*guard, 100);
391        } // guard被drop,锁被释放
392
393        assert!(!lock.is_locked());
394
395        // 验证值被修改
396        let guard = lock.lock();
397        assert_eq!(*guard, 100);
398    }
399
400    #[test]
401    fn test_multiple_types() {
402        // 测试不同类型的数据
403        let string_lock = IrqSpinlock::new(String::from("hello"));
404        {
405            let mut guard = string_lock.lock();
406            guard.push_str(" world");
407            assert_eq!(guard.as_str(), "hello world");
408        }
409
410        let array_lock = IrqSpinlock::new([1, 2, 3]);
411        {
412            let guard = array_lock.lock();
413            assert_eq!(*guard, [1, 2, 3]);
414        }
415
416        let struct_lock = IrqSpinlock::new((42, "test"));
417        {
418            let guard = struct_lock.lock();
419            assert_eq!(guard.0, 42);
420            assert_eq!(guard.1, "test");
421        }
422    }
423}