1 /** 2 * @file spinlock.h 3 * @author fslongjin (longjin@RinGoTek.cn) 4 * @brief 自旋锁 5 * @version 0.1 6 * @date 2022-04-07 7 * 8 * @copyright Copyright (c) 2022 9 * 10 */ 11 #pragma once 12 #include <asm/irqflags.h> 13 #include <common/glib.h> 14 #include <debug/bug.h> 15 16 /** 17 * @brief 定义自旋锁结构体 18 * 19 */ 20 typedef struct 21 { 22 int8_t lock; // 1:unlocked 0:locked 23 } spinlock_t; 24 25 extern void __arch_spin_lock(spinlock_t *lock); 26 extern void __arch_spin_unlock(spinlock_t *lock); 27 28 extern void __arch_spin_lock_no_preempt(spinlock_t *lock); 29 extern void __arch_spin_unlock_no_preempt(spinlock_t *lock); 30 31 extern long __arch_spin_trylock(spinlock_t *lock); 32 33 /** 34 * @brief 自旋锁加锁 35 * 36 * @param lock 37 */ spin_lock(spinlock_t * lock)38void spin_lock(spinlock_t *lock) 39 { 40 __arch_spin_lock(lock); 41 } 42 43 /** 44 * @brief 自旋锁解锁 45 * 46 * @param lock 47 */ spin_unlock(spinlock_t * lock)48void spin_unlock(spinlock_t *lock) 49 { 50 __arch_spin_unlock(lock); 51 } 52 53 /** 54 * @brief 初始化自旋锁 55 * 56 * @param lock 57 */ spin_init(spinlock_t * lock)58void spin_init(spinlock_t *lock) 59 { 60 barrier(); 61 lock->lock = 1; 62 barrier(); 63 } 64 65 /** 66 * @brief 自旋锁加锁(不改变自旋锁持有计数) 67 * 68 * @warning 慎用此函数,除非你有十足的把握不会产生自旋锁计数错误 69 */ spin_lock_no_preempt(spinlock_t * lock)70void spin_lock_no_preempt(spinlock_t *lock) 71 { 72 __arch_spin_lock_no_preempt(lock); 73 } 74 75 /** 76 * @brief 自旋锁解锁(不改变自旋锁持有计数) 77 * 78 * @warning 慎用此函数,除非你有十足的把握不会产生自旋锁计数错误 79 */ spin_unlock_no_preempt(spinlock_t * lock)80void spin_unlock_no_preempt(spinlock_t *lock) 81 { 82 __arch_spin_unlock_no_preempt(lock); 83 } 84 85 /** 86 * @brief 尝试加锁 87 * 88 * @param lock 89 * @return long 锁变量的值(1为成功加锁,0为加锁失败) 90 */ spin_trylock(spinlock_t * lock)91long spin_trylock(spinlock_t *lock) 92 { 93 return __arch_spin_trylock(lock); 94 } 95 96 /** 97 * @brief 保存中断状态,关闭中断,并自旋锁加锁 98 * 99 */ 100 #define spin_lock_irqsave(lock, flags) \ 101 do \ 102 { \ 103 local_irq_save(flags); \ 104 spin_lock(lock); \ 105 } while (0) 106 107 /** 108 * @brief 恢复rflags以及中断状态并解锁自旋锁 109 * 110 */ 111 #define spin_unlock_irqrestore(lock, flags) \ 112 do \ 113 { \ 114 spin_unlock(lock); \ 115 local_irq_restore(flags); \ 116 } while (0) 117 118 /** 119 * @brief 关闭中断并加锁 120 * 121 */ 122 #define spin_lock_irq(lock) \ 123 do \ 124 { \ 125 local_irq_disable(); \ 126 spin_lock(lock); \ 127 } while (0) 128 129 /** 130 * @brief 解锁并开启中断 131 * 132 */ 133 #define spin_unlock_irq(lock) \ 134 do \ 135 { \ 136 spin_unlock(lock); \ 137 local_irq_enable(); \ 138 } while (0) 139 140 /** 141 * @brief 判断自旋锁是否已经加锁 142 * 143 * @param lock 待判断的自旋锁 144 * @return true 已经加锁 145 * @return false 尚未加锁 146 */ spin_is_locked(const spinlock_t * lock)147static inline bool spin_is_locked(const spinlock_t *lock) 148 { 149 int x = READ_ONCE(lock->lock); 150 return (x == 0) ? true : false; 151 } 152 153 #define assert_spin_locked(lock) BUG_ON(!spin_is_locked(lock))