1 #pragma once 2 3 #include <common/sys/types.h> 4 #include <common/spinlock.h> 5 6 #if ARCH(X86_64) 7 // 仅在x64架构下启用cmpxchg 8 #define __LOCKREF_ENABLE_CMPXCHG__ 9 #endif 10 struct lockref 11 { 12 union 13 { 14 #ifdef __LOCKREF_ENABLE_CMPXCHG__ 15 aligned_u64 lock_count; // 通过该变量的声明,使得整个lockref按照8字节对齐 16 #endif 17 struct 18 { 19 spinlock_t lock; 20 int count; 21 }; 22 }; 23 }; 24 25 /** 26 * @brief 原子的将引用计数加1 27 * 28 * @param lock_ref 要被操作的lockref变量 29 */ 30 void lockref_inc(struct lockref *lock_ref); 31 32 /** 33 * @brief 原子地将引用计数加1.如果原来的count≤0,则操作失败。 34 * 35 * @param lock_ref 指向要被操作的lockref变量的指针 36 * @return int 操作成功=>true 37 * 操作失败=>false 38 */ 39 bool lockref_inc_not_zero(struct lockref *lock_ref); 40 41 /** 42 * @brief 原子地减少引用计数。如果已处于count≤0的状态,则返回-1 43 * 44 * 本函数与lockref_dec_return()的区别在于,当在cmpxchg()中检测到count<=0或已加锁,本函数会再次尝试通过加锁来执行操作 45 * 而后者会直接返回错误 46 * 47 * @param lock_ref 指向要被操作的lockref变量的指针 48 * @return int 操作成功 => 返回新的引用变量值 49 * lockref处于count≤0的状态 => 返回-1 50 */ 51 int lockref_dec(struct lockref *lock_ref); 52 53 /** 54 * @brief 原子地减少引用计数。如果处于已加锁或count≤0的状态,则返回-1 55 * 56 * 本函数与lockref_dec()的区别在于,当在cmpxchg()中检测到count<=0或已加锁,本函数会直接返回错误 57 * 而后者会再次尝试通过加锁来执行操作 58 * 59 * @param lock_ref 指向要被操作的lockref变量的指针 60 * @return int 操作成功 => 返回新的引用变量值 61 * lockref处于已加锁或count≤0的状态 => 返回-1 62 */ 63 int lockref_dec_return(struct lockref *lock_ref); 64 65 66 /** 67 * @brief 原子地减少引用计数。若当前的引用计数≤1,则操作失败 68 * 69 * 该函数与lockref_dec_or_lock_not_zero()的区别在于,当cmpxchg()时发现old.count≤1时,该函数会直接返回false. 70 * 而后者在这种情况下,会尝试加锁来进行操作。 71 * 72 * @param lock_ref 指向要被操作的lockref变量的指针 73 * @return true 成功将引用计数减1 74 * @return false 如果当前的引用计数≤1,操作失败 75 */ 76 bool lockref_dec_not_zero(struct lockref *lock_ref); 77 78 /** 79 * @brief 原子地减少引用计数。若当前的引用计数≤1,则操作失败 80 * 81 * 该函数与lockref_dec_not_zero()的区别在于,当cmpxchg()时发现old.count≤1时,该函数会尝试加锁来进行操作。 82 * 而后者在这种情况下,会直接返回false. 83 * 84 * @param lock_ref 指向要被操作的lockref变量的指针 85 * @return true 成功将引用计数减1 86 * @return false 如果当前的引用计数≤1,操作失败 87 */ 88 bool lockref_dec_or_lock_not_zero(struct lockref *lock_ref); 89 90 /** 91 * @brief 将lockref变量标记为已经死亡(将count设置为负值) 92 * 93 * @param lock_ref 指向要被操作的lockref变量的指针 94 */ 95 void lockref_mark_dead(struct lockref * lock_ref); 96 97 /** 98 * @brief 自增引用计数。(除非该lockref已经死亡) 99 * 100 * @param lock_ref 指向要被操作的lockref变量的指针 101 * @return true 操作成功 102 * @return false 操作失败,lockref已死亡 103 */ 104 bool lockref_inc_not_dead(struct lockref *lock_ref);