xref: /DragonOS/kernel/src/libs/spinlock.rs (revision d4f3de93a23e4bd4f000a3663768d47d094bf188)
166f67c6aSlogin #![allow(dead_code)]
266f67c6aSlogin use core::ptr::read_volatile;
366f67c6aSlogin 
4ac643d42Slogin use core::sync::atomic::{AtomicBool, Ordering};
5ac643d42Slogin 
6adc1846bSlogin use crate::arch::asm::irqflags::{local_irq_restore, local_irq_save};
7adc1846bSlogin use crate::arch::interrupt::{cli, sti};
866f67c6aSlogin use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
9ac643d42Slogin use crate::process::preempt::{preempt_disable, preempt_enable};
1066f67c6aSlogin 
1166f67c6aSlogin /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
121a2eaa40Slogin #[inline]
1366f67c6aSlogin pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
1466f67c6aSlogin     local_irq_save(flags);
1566f67c6aSlogin     unsafe {
1666f67c6aSlogin         spin_lock(lock);
1766f67c6aSlogin     }
1866f67c6aSlogin }
1966f67c6aSlogin 
2066f67c6aSlogin /// @brief 恢复rflags以及中断状态并解锁自旋锁
211a2eaa40Slogin #[inline]
2266f67c6aSlogin pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
2366f67c6aSlogin     unsafe {
2466f67c6aSlogin         spin_unlock(lock);
2566f67c6aSlogin     }
2666f67c6aSlogin     // kdebug!("123");
2766f67c6aSlogin     local_irq_restore(flags);
2866f67c6aSlogin }
2966f67c6aSlogin 
3066f67c6aSlogin /// 判断一个自旋锁是否已经被加锁
311a2eaa40Slogin #[inline]
3266f67c6aSlogin pub fn spin_is_locked(lock: &spinlock_t) -> bool {
3366f67c6aSlogin     let val = unsafe { read_volatile(&lock.lock as *const i8) };
3466f67c6aSlogin 
3566f67c6aSlogin     return if val == 0 { true } else { false };
3666f67c6aSlogin }
37c8025a88Slogin 
38c8025a88Slogin impl Default for spinlock_t {
39c8025a88Slogin     fn default() -> Self {
40c8025a88Slogin         Self { lock: 1 }
41c8025a88Slogin     }
42c8025a88Slogin }
431a2eaa40Slogin 
441a2eaa40Slogin /// @brief 关闭中断并加锁
451a2eaa40Slogin pub fn spin_lock_irq(lock: *mut spinlock_t) {
461a2eaa40Slogin     cli();
47ac643d42Slogin     unsafe {
48ac643d42Slogin         spin_lock(lock);
49ac643d42Slogin     }
501a2eaa40Slogin }
511a2eaa40Slogin 
521a2eaa40Slogin /// @brief 解锁并开中断
531a2eaa40Slogin pub fn spin_unlock_irq(lock: *mut spinlock_t) {
54ac643d42Slogin     unsafe {
55ac643d42Slogin         spin_unlock(lock);
56ac643d42Slogin     }
571a2eaa40Slogin     sti();
581a2eaa40Slogin }
59ac643d42Slogin 
60*d4f3de93Slogin #[derive(Debug)]
61ac643d42Slogin pub struct RawSpinlock(AtomicBool);
62ac643d42Slogin 
63ac643d42Slogin impl RawSpinlock {
64ac643d42Slogin     /// @brief 初始化自旋锁
65*d4f3de93Slogin     pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
66ac643d42Slogin 
67ac643d42Slogin     /// @brief 加锁
68ac643d42Slogin     pub fn lock(&mut self) {
69ac643d42Slogin         while !self.try_lock() {}
70ac643d42Slogin     }
71ac643d42Slogin 
72ac643d42Slogin     /// @brief 关中断并加锁
73ac643d42Slogin     pub fn lock_irq(&mut self){
74ac643d42Slogin         cli();
75ac643d42Slogin         self.lock();
76ac643d42Slogin     }
77ac643d42Slogin 
78ac643d42Slogin     /// @brief 尝试加锁
79ac643d42Slogin     /// @return 加锁成功->true
80ac643d42Slogin     ///         加锁失败->false
81ac643d42Slogin     pub fn try_lock(&mut self) -> bool {
82ac643d42Slogin         // 先增加自旋锁持有计数
83ac643d42Slogin         preempt_disable();
84ac643d42Slogin 
85ac643d42Slogin         let res = self
86ac643d42Slogin             .0
87ac643d42Slogin             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
88ac643d42Slogin             .is_ok();
89ac643d42Slogin 
90ac643d42Slogin         // 如果加锁失败恢复自旋锁持有计数
91ac643d42Slogin         if res == false {
92ac643d42Slogin             preempt_enable();
93ac643d42Slogin         }
94ac643d42Slogin         return res;
95ac643d42Slogin     }
96ac643d42Slogin 
97ac643d42Slogin     /// @brief 解锁
98ac643d42Slogin     pub fn unlock(&mut self){
99ac643d42Slogin         // 减少自旋锁持有计数
100ac643d42Slogin         preempt_enable();
101ac643d42Slogin         self.0.store(false, Ordering::Release);
102ac643d42Slogin     }
103ac643d42Slogin 
104ac643d42Slogin     /// @brief 放锁并开中断
105ac643d42Slogin     pub fn unlock_irq(&mut self){
106ac643d42Slogin         self.unlock();
107ac643d42Slogin         sti();
108ac643d42Slogin     }
109ac643d42Slogin 
110ac643d42Slogin     // todo: spin_lock_irqsave
111ac643d42Slogin     // todo: spin_unlock_irqrestore
112ac643d42Slogin 
113ac643d42Slogin }
114