xref: /DragonOS/kernel/src/common/spinlock.h (revision cffd7144fbed84f9775e89d7b99602c6ccc5a510)
12813126eSlogin /**
22813126eSlogin  * @file spinlock.h
32813126eSlogin  * @author fslongjin (longjin@RinGoTek.cn)
42813126eSlogin  * @brief 自旋锁
52813126eSlogin  * @version 0.1
62813126eSlogin  * @date 2022-04-07
72813126eSlogin  *
82813126eSlogin  * @copyright Copyright (c) 2022
92813126eSlogin  *
102813126eSlogin  */
112813126eSlogin #pragma once
12*cffd7144Slogin #include <asm/irqflags.h>
132813126eSlogin #include <common/glib.h>
142813126eSlogin #include <debug/bug.h>
152813126eSlogin 
162813126eSlogin /**
172813126eSlogin  * @brief 定义自旋锁结构体
182813126eSlogin  *
192813126eSlogin  */
202813126eSlogin typedef struct
212813126eSlogin {
222813126eSlogin     int8_t lock; // 1:unlocked 0:locked
232813126eSlogin } spinlock_t;
242813126eSlogin 
25*cffd7144Slogin extern void __arch_spin_lock(spinlock_t *lock);
26*cffd7144Slogin extern void __arch_spin_unlock(spinlock_t *lock);
27*cffd7144Slogin 
28*cffd7144Slogin extern void __arch_spin_lock_no_preempt(spinlock_t *lock);
29*cffd7144Slogin extern void __arch_spin_unlock_no_preempt(spinlock_t *lock);
30*cffd7144Slogin 
31*cffd7144Slogin extern long __arch_spin_trylock(spinlock_t *lock);
32*cffd7144Slogin 
332813126eSlogin /**
342813126eSlogin  * @brief 自旋锁加锁
352813126eSlogin  *
362813126eSlogin  * @param lock
372813126eSlogin  */
spin_lock(spinlock_t * lock)382813126eSlogin void spin_lock(spinlock_t *lock)
392813126eSlogin {
40*cffd7144Slogin     __arch_spin_lock(lock);
412813126eSlogin }
422813126eSlogin 
432813126eSlogin /**
442813126eSlogin  * @brief 自旋锁解锁
452813126eSlogin  *
462813126eSlogin  * @param lock
472813126eSlogin  */
spin_unlock(spinlock_t * lock)482813126eSlogin void spin_unlock(spinlock_t *lock)
492813126eSlogin {
50*cffd7144Slogin     __arch_spin_unlock(lock);
512813126eSlogin }
522813126eSlogin 
532813126eSlogin /**
542813126eSlogin  * @brief 初始化自旋锁
552813126eSlogin  *
562813126eSlogin  * @param lock
572813126eSlogin  */
spin_init(spinlock_t * lock)582813126eSlogin void spin_init(spinlock_t *lock)
592813126eSlogin {
602813126eSlogin     barrier();
612813126eSlogin     lock->lock = 1;
622813126eSlogin     barrier();
632813126eSlogin }
642813126eSlogin 
652813126eSlogin /**
662813126eSlogin  * @brief 自旋锁加锁(不改变自旋锁持有计数)
672813126eSlogin  *
682813126eSlogin  * @warning 慎用此函数,除非你有十足的把握不会产生自旋锁计数错误
692813126eSlogin  */
spin_lock_no_preempt(spinlock_t * lock)702813126eSlogin void spin_lock_no_preempt(spinlock_t *lock)
712813126eSlogin {
72*cffd7144Slogin     __arch_spin_lock_no_preempt(lock);
732813126eSlogin }
74*cffd7144Slogin 
752813126eSlogin /**
762813126eSlogin  * @brief 自旋锁解锁(不改变自旋锁持有计数)
772813126eSlogin  *
782813126eSlogin  * @warning 慎用此函数,除非你有十足的把握不会产生自旋锁计数错误
792813126eSlogin  */
spin_unlock_no_preempt(spinlock_t * lock)802813126eSlogin void spin_unlock_no_preempt(spinlock_t *lock)
812813126eSlogin {
82*cffd7144Slogin     __arch_spin_unlock_no_preempt(lock);
832813126eSlogin }
842813126eSlogin 
852813126eSlogin /**
862813126eSlogin  * @brief 尝试加锁
872813126eSlogin  *
882813126eSlogin  * @param lock
892813126eSlogin  * @return long 锁变量的值(1为成功加锁,0为加锁失败)
902813126eSlogin  */
spin_trylock(spinlock_t * lock)912813126eSlogin long spin_trylock(spinlock_t *lock)
922813126eSlogin {
93*cffd7144Slogin     return __arch_spin_trylock(lock);
942813126eSlogin }
952813126eSlogin 
962813126eSlogin /**
972813126eSlogin  * @brief 保存中断状态,关闭中断,并自旋锁加锁
982813126eSlogin  *
992813126eSlogin  */
1002813126eSlogin #define spin_lock_irqsave(lock, flags)                                                                                 \
1012813126eSlogin     do                                                                                                                 \
1022813126eSlogin     {                                                                                                                  \
1032813126eSlogin         local_irq_save(flags);                                                                                         \
1042813126eSlogin         spin_lock(lock);                                                                                               \
1052813126eSlogin     } while (0)
1062813126eSlogin 
1072813126eSlogin /**
1082813126eSlogin  * @brief 恢复rflags以及中断状态并解锁自旋锁
1092813126eSlogin  *
1102813126eSlogin  */
1112813126eSlogin #define spin_unlock_irqrestore(lock, flags)                                                                            \
1122813126eSlogin     do                                                                                                                 \
1132813126eSlogin     {                                                                                                                  \
1142813126eSlogin         spin_unlock(lock);                                                                                             \
1152813126eSlogin         local_irq_restore(flags);                                                                                      \
1162813126eSlogin     } while (0)
1172813126eSlogin 
1182813126eSlogin /**
1192813126eSlogin  * @brief 关闭中断并加锁
1202813126eSlogin  *
1212813126eSlogin  */
1222813126eSlogin #define spin_lock_irq(lock)                                                                                            \
1232813126eSlogin     do                                                                                                                 \
1242813126eSlogin     {                                                                                                                  \
1252813126eSlogin         local_irq_disable();                                                                                           \
1262813126eSlogin         spin_lock(lock);                                                                                               \
1272813126eSlogin     } while (0)
1282813126eSlogin 
1292813126eSlogin /**
1302813126eSlogin  * @brief 解锁并开启中断
1312813126eSlogin  *
1322813126eSlogin  */
1332813126eSlogin #define spin_unlock_irq(lock)                                                                                          \
1342813126eSlogin     do                                                                                                                 \
1352813126eSlogin     {                                                                                                                  \
1362813126eSlogin         spin_unlock(lock);                                                                                             \
1372813126eSlogin         local_irq_enable();                                                                                            \
1382813126eSlogin     } while (0)
1392813126eSlogin 
1402813126eSlogin /**
1412813126eSlogin  * @brief 判断自旋锁是否已经加锁
1422813126eSlogin  *
1432813126eSlogin  * @param lock 待判断的自旋锁
1442813126eSlogin  * @return true 已经加锁
1452813126eSlogin  * @return false 尚未加锁
1462813126eSlogin  */
spin_is_locked(const spinlock_t * lock)1472813126eSlogin static inline bool spin_is_locked(const spinlock_t *lock)
1482813126eSlogin {
1492813126eSlogin     int x = READ_ONCE(lock->lock);
1502813126eSlogin     return (x == 0) ? true : false;
1512813126eSlogin }
1522813126eSlogin 
1532813126eSlogin #define assert_spin_locked(lock) BUG_ON(!spin_is_locked(lock))