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);