Browse Source

new:新增rust写的RawSpinlock (#127)

login 2 years ago
parent
commit
ac643d420b
1 changed files with 66 additions and 5 deletions
  1. 66 5
      kernel/src/libs/spinlock.rs

+ 66 - 5
kernel/src/libs/spinlock.rs

@@ -1,9 +1,12 @@
 #![allow(dead_code)]
 use core::ptr::read_volatile;
 
+use core::sync::atomic::{AtomicBool, Ordering};
+
 use crate::arch::x86_64::asm::irqflags::{local_irq_restore, local_irq_save};
 use crate::arch::x86_64::interrupt::{cli, sti};
 use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
+use crate::process::preempt::{preempt_disable, preempt_enable};
 
 /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
 #[inline]
@@ -39,13 +42,71 @@ impl Default for spinlock_t {
 }
 
 /// @brief 关闭中断并加锁
-pub fn spin_lock_irq(lock: *mut spinlock_t){
+pub fn spin_lock_irq(lock: *mut spinlock_t) {
     cli();
-    unsafe{spin_lock(lock);}
+    unsafe {
+        spin_lock(lock);
+    }
 }
 
 /// @brief 解锁并开中断
-pub fn spin_unlock_irq(lock: *mut spinlock_t){
-    unsafe{spin_unlock(lock);}
+pub fn spin_unlock_irq(lock: *mut spinlock_t) {
+    unsafe {
+        spin_unlock(lock);
+    }
     sti();
-}
+}
+
+pub struct RawSpinlock(AtomicBool);
+
+impl RawSpinlock {
+    /// @brief 初始化自旋锁
+    const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
+
+    /// @brief 加锁
+    pub fn lock(&mut self) {
+        while !self.try_lock() {}
+    }
+
+    /// @brief 关中断并加锁
+    pub fn lock_irq(&mut self){
+        cli();
+        self.lock();
+    }
+
+    /// @brief 尝试加锁
+    /// @return 加锁成功->true
+    ///         加锁失败->false
+    pub fn try_lock(&mut self) -> bool {
+        // 先增加自旋锁持有计数
+        preempt_disable();
+
+        let res = self
+            .0
+            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
+            .is_ok();
+        
+        // 如果加锁失败恢复自旋锁持有计数
+        if res == false {
+            preempt_enable();
+        }
+        return res;
+    }
+
+    /// @brief 解锁
+    pub fn unlock(&mut self){
+        // 减少自旋锁持有计数
+        preempt_enable();
+        self.0.store(false, Ordering::Release);
+    }
+
+    /// @brief 放锁并开中断
+    pub fn unlock_irq(&mut self){
+        self.unlock();
+        sti();
+    }
+
+    // todo: spin_lock_irqsave
+    // todo: spin_unlock_irqrestore
+
+}