xref: /DragonOS/kernel/src/libs/spinlock.rs (revision ac643d420b22f9d454ecefccd51ed34a9664586b)
166f67c6aSlogin #![allow(dead_code)]
266f67c6aSlogin use core::ptr::read_volatile;
366f67c6aSlogin 
4*ac643d42Slogin use core::sync::atomic::{AtomicBool, Ordering};
5*ac643d42Slogin 
666f67c6aSlogin use crate::arch::x86_64::asm::irqflags::{local_irq_restore, local_irq_save};
71a2eaa40Slogin use crate::arch::x86_64::interrupt::{cli, sti};
866f67c6aSlogin use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
9*ac643d42Slogin 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();
47*ac643d42Slogin     unsafe {
48*ac643d42Slogin         spin_lock(lock);
49*ac643d42Slogin     }
501a2eaa40Slogin }
511a2eaa40Slogin 
521a2eaa40Slogin /// @brief 解锁并开中断
531a2eaa40Slogin pub fn spin_unlock_irq(lock: *mut spinlock_t) {
54*ac643d42Slogin     unsafe {
55*ac643d42Slogin         spin_unlock(lock);
56*ac643d42Slogin     }
571a2eaa40Slogin     sti();
581a2eaa40Slogin }
59*ac643d42Slogin 
60*ac643d42Slogin pub struct RawSpinlock(AtomicBool);
61*ac643d42Slogin 
62*ac643d42Slogin impl RawSpinlock {
63*ac643d42Slogin     /// @brief 初始化自旋锁
64*ac643d42Slogin     const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
65*ac643d42Slogin 
66*ac643d42Slogin     /// @brief 加锁
67*ac643d42Slogin     pub fn lock(&mut self) {
68*ac643d42Slogin         while !self.try_lock() {}
69*ac643d42Slogin     }
70*ac643d42Slogin 
71*ac643d42Slogin     /// @brief 关中断并加锁
72*ac643d42Slogin     pub fn lock_irq(&mut self){
73*ac643d42Slogin         cli();
74*ac643d42Slogin         self.lock();
75*ac643d42Slogin     }
76*ac643d42Slogin 
77*ac643d42Slogin     /// @brief 尝试加锁
78*ac643d42Slogin     /// @return 加锁成功->true
79*ac643d42Slogin     ///         加锁失败->false
80*ac643d42Slogin     pub fn try_lock(&mut self) -> bool {
81*ac643d42Slogin         // 先增加自旋锁持有计数
82*ac643d42Slogin         preempt_disable();
83*ac643d42Slogin 
84*ac643d42Slogin         let res = self
85*ac643d42Slogin             .0
86*ac643d42Slogin             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
87*ac643d42Slogin             .is_ok();
88*ac643d42Slogin 
89*ac643d42Slogin         // 如果加锁失败恢复自旋锁持有计数
90*ac643d42Slogin         if res == false {
91*ac643d42Slogin             preempt_enable();
92*ac643d42Slogin         }
93*ac643d42Slogin         return res;
94*ac643d42Slogin     }
95*ac643d42Slogin 
96*ac643d42Slogin     /// @brief 解锁
97*ac643d42Slogin     pub fn unlock(&mut self){
98*ac643d42Slogin         // 减少自旋锁持有计数
99*ac643d42Slogin         preempt_enable();
100*ac643d42Slogin         self.0.store(false, Ordering::Release);
101*ac643d42Slogin     }
102*ac643d42Slogin 
103*ac643d42Slogin     /// @brief 放锁并开中断
104*ac643d42Slogin     pub fn unlock_irq(&mut self){
105*ac643d42Slogin         self.unlock();
106*ac643d42Slogin         sti();
107*ac643d42Slogin     }
108*ac643d42Slogin 
109*ac643d42Slogin     // todo: spin_lock_irqsave
110*ac643d42Slogin     // todo: spin_unlock_irqrestore
111*ac643d42Slogin 
112*ac643d42Slogin }
113