|
@@ -1,4 +1,6 @@
|
|
#![allow(dead_code)]
|
|
#![allow(dead_code)]
|
|
|
|
+use core::cell::UnsafeCell;
|
|
|
|
+use core::ops::{Deref, DerefMut};
|
|
use core::ptr::read_volatile;
|
|
use core::ptr::read_volatile;
|
|
|
|
|
|
use core::sync::atomic::{AtomicBool, Ordering};
|
|
use core::sync::atomic::{AtomicBool, Ordering};
|
|
@@ -59,7 +61,7 @@ pub fn spin_unlock_irq(lock: *mut spinlock_t) {
|
|
|
|
|
|
/// 原始的Spinlock(自旋锁)
|
|
/// 原始的Spinlock(自旋锁)
|
|
/// 请注意,这个自旋锁和C的不兼容。
|
|
/// 请注意,这个自旋锁和C的不兼容。
|
|
-///
|
|
|
|
|
|
+///
|
|
/// @param self.0 这个AtomicBool的值为false时,表示没有被加锁。当它为true时,表示自旋锁已经被上锁。
|
|
/// @param self.0 这个AtomicBool的值为false时,表示没有被加锁。当它为true时,表示自旋锁已经被上锁。
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
pub struct RawSpinlock(AtomicBool);
|
|
pub struct RawSpinlock(AtomicBool);
|
|
@@ -69,12 +71,12 @@ impl RawSpinlock {
|
|
pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
|
|
pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
|
|
|
|
|
|
/// @brief 加锁
|
|
/// @brief 加锁
|
|
- pub fn lock(&mut self) {
|
|
|
|
|
|
+ pub fn lock(&self) {
|
|
while !self.try_lock() {}
|
|
while !self.try_lock() {}
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief 关中断并加锁
|
|
/// @brief 关中断并加锁
|
|
- pub fn lock_irq(&mut self){
|
|
|
|
|
|
+ pub fn lock_irq(&self) {
|
|
cli();
|
|
cli();
|
|
self.lock();
|
|
self.lock();
|
|
}
|
|
}
|
|
@@ -82,7 +84,7 @@ impl RawSpinlock {
|
|
/// @brief 尝试加锁
|
|
/// @brief 尝试加锁
|
|
/// @return 加锁成功->true
|
|
/// @return 加锁成功->true
|
|
/// 加锁失败->false
|
|
/// 加锁失败->false
|
|
- pub fn try_lock(&mut self) -> bool {
|
|
|
|
|
|
+ pub fn try_lock(&self) -> bool {
|
|
// 先增加自旋锁持有计数
|
|
// 先增加自旋锁持有计数
|
|
preempt_disable();
|
|
preempt_disable();
|
|
|
|
|
|
@@ -90,7 +92,7 @@ impl RawSpinlock {
|
|
.0
|
|
.0
|
|
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
|
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
|
.is_ok();
|
|
.is_ok();
|
|
-
|
|
|
|
|
|
+
|
|
// 如果加锁失败恢复自旋锁持有计数
|
|
// 如果加锁失败恢复自旋锁持有计数
|
|
if res == false {
|
|
if res == false {
|
|
preempt_enable();
|
|
preempt_enable();
|
|
@@ -99,34 +101,92 @@ impl RawSpinlock {
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief 解锁
|
|
/// @brief 解锁
|
|
- pub fn unlock(&mut self){
|
|
|
|
|
|
+ pub fn unlock(&self) {
|
|
// 减少自旋锁持有计数
|
|
// 减少自旋锁持有计数
|
|
preempt_enable();
|
|
preempt_enable();
|
|
self.0.store(false, Ordering::Release);
|
|
self.0.store(false, Ordering::Release);
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief 放锁并开中断
|
|
/// @brief 放锁并开中断
|
|
- pub fn unlock_irq(&mut self){
|
|
|
|
|
|
+ pub fn unlock_irq(&self) {
|
|
self.unlock();
|
|
self.unlock();
|
|
sti();
|
|
sti();
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief 判断自旋锁是否被上锁
|
|
/// @brief 判断自旋锁是否被上锁
|
|
- ///
|
|
|
|
|
|
+ ///
|
|
/// @return true 自旋锁被上锁
|
|
/// @return true 自旋锁被上锁
|
|
/// @return false 自旋锁处于解锁状态
|
|
/// @return false 自旋锁处于解锁状态
|
|
- pub fn is_locked(&self)->bool
|
|
|
|
- {
|
|
|
|
|
|
+ pub fn is_locked(&self) -> bool {
|
|
return self.0.load(Ordering::Relaxed).into();
|
|
return self.0.load(Ordering::Relaxed).into();
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief 强制设置自旋锁的状态
|
|
/// @brief 强制设置自旋锁的状态
|
|
/// 请注意,这样操作可能会带来未知的风险。因此它是unsafe的。(尽管从Rust语言本身来说,它是safe的)
|
|
/// 请注意,这样操作可能会带来未知的风险。因此它是unsafe的。(尽管从Rust语言本身来说,它是safe的)
|
|
- pub unsafe fn set_value(&mut self, value:bool){
|
|
|
|
|
|
+ pub unsafe fn set_value(&mut self, value: bool) {
|
|
self.0.store(value, Ordering::SeqCst);
|
|
self.0.store(value, Ordering::SeqCst);
|
|
}
|
|
}
|
|
|
|
|
|
// todo: spin_lock_irqsave
|
|
// todo: spin_lock_irqsave
|
|
// todo: spin_unlock_irqrestore
|
|
// todo: spin_unlock_irqrestore
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// 实现了守卫的SpinLock, 能够支持内部可变性
|
|
|
|
+///
|
|
|
|
+#[derive(Debug)]
|
|
|
|
+pub struct SpinLock<T> {
|
|
|
|
+ lock: RawSpinlock,
|
|
|
|
+ /// 自旋锁保护的数据
|
|
|
|
+ data: UnsafeCell<T>,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// SpinLock的守卫
|
|
|
|
+/// 该守卫没有构造器,并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。
|
|
|
|
+/// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。
|
|
|
|
+#[derive(Debug)]
|
|
|
|
+pub struct SpinLockGuard<'a, T: 'a> {
|
|
|
|
+ lock: &'a SpinLock<T>,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// 向编译器保证,SpinLock在线程之间是安全的.
|
|
|
|
+/// 其中要求类型T实现了Send这个Trait
|
|
|
|
+unsafe impl<T> Sync for SpinLock<T> where T: Send {}
|
|
|
|
+
|
|
|
|
+impl<T> SpinLock<T> {
|
|
|
|
+ pub const fn new(value: T) -> Self {
|
|
|
|
+ return Self {
|
|
|
|
+ lock: RawSpinlock::INIT,
|
|
|
|
+ data: UnsafeCell::new(value),
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ #[inline(always)]
|
|
|
|
+ pub fn lock(&self) -> SpinLockGuard<T> {
|
|
|
|
+ self.lock.lock();
|
|
|
|
+ // 加锁成功,返回一个守卫
|
|
|
|
+ return SpinLockGuard { lock: self };
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
|
|
|
|
+impl<T> Deref for SpinLockGuard<'_, T> {
|
|
|
|
+ type Target = T;
|
|
|
|
+
|
|
|
|
+ fn deref(&self) -> &Self::Target {
|
|
|
|
+ return unsafe { &*self.lock.data.get() };
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用
|
|
|
|
+impl<T> DerefMut for SpinLockGuard<'_, T> {
|
|
|
|
+ fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
+ return unsafe { &mut *self.lock.data.get() };
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
|
|
|
|
+impl<T> Drop for SpinLockGuard<'_, T> {
|
|
|
|
+ fn drop(&mut self) {
|
|
|
|
+ self.lock.lock.unlock();
|
|
|
|
+ }
|
|
}
|
|
}
|