1 #![allow(dead_code)]
2 use super::spinlock::RawSpinlock;
3 use crate::{arch::asm::cmpxchg::try_cmpxchg_q, syscall::SystemError};
4 use core::{fmt::Debug, intrinsics::size_of};
5 
6 #[cfg(target_arch = "x86_64")]
7 /// 由于需要cmpxchg,所以整个lockref按照8字节对齐
8 #[repr(align(8))]
9 #[derive(Debug)]
10 pub struct LockRef {
11     pub lock: RawSpinlock,
12     pub count: i32,
13 }
14 
15 /// 除了x86_64以外的架构,不使用cmpxchg进行优化
16 #[cfg(not(target_arch = "x86_64"))]
17 pub struct LockRef {
18     lock: RawSpinlock,
19     count: i32,
20 }
21 
22 enum CmpxchgMode {
23     Increase,
24     IncreaseNotZero,
25     IncreaseNotDead,
26     Decrease,
27     DecreaseReturn,
28     DecreaseNotZero,
29     DecreaseOrLockNotZero,
30 }
31 
32 impl LockRef {
33     pub const INIT: LockRef = LockRef {
34         lock: RawSpinlock::INIT,
35         count: 0,
36     };
37 
new() -> LockRef38     pub fn new() -> LockRef {
39         assert_eq!(size_of::<LockRef>(), 8);
40         return LockRef::INIT;
41     }
42 
43     /// @brief 为X86架构实现cmpxchg循环,以支持无锁操作。
44     ///
45     /// @return 操作成功:返回Ok(new.count)
46     /// @return 操作失败,原因:超时 => 返回Err(SystemError::ETIMEDOUT)
47     /// @return 操作失败,原因:不满足规则 => 返回Err(SystemError::E2BIG)
48     #[cfg(target_arch = "x86_64")]
49     #[inline]
cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32>50     fn cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32> {
51         use core::ptr::read_volatile;
52 
53         use crate::arch::cpu::cpu_relax;
54 
55         let mut old: LockRef = LockRef::INIT;
56         old.count = unsafe { read_volatile(&self.count) };
57         for _ in 0..100 {
58             if !old.lock.is_locked() {
59                 let mut new = LockRef::INIT;
60                 unsafe {
61                     *(&mut new as *mut LockRef as *mut usize as *mut u64) =
62                         read_volatile(&mut old as *mut LockRef as *mut usize as *mut u64);
63                     new.lock.set_value(false);
64                 }
65 
66                 // 根据不同情况,执行不同代码
67                 match mode {
68                     CmpxchgMode::Increase => {
69                         new.count += 1;
70                     }
71                     CmpxchgMode::IncreaseNotZero => {
72                         // 操作失败
73                         if old.count <= 0 {
74                             return Err(1);
75                         }
76                         new.count += 1;
77                     }
78 
79                     CmpxchgMode::IncreaseNotDead => {
80                         if old.count < 0 {
81                             return Err(1);
82                         }
83                         new.count += 1;
84                     }
85 
86                     CmpxchgMode::Decrease | CmpxchgMode::DecreaseReturn => {
87                         if old.count <= 0 {
88                             return Err(1);
89                         }
90                         new.count -= 1;
91                     }
92                     CmpxchgMode::DecreaseNotZero | CmpxchgMode::DecreaseOrLockNotZero => {
93                         if old.count <= 1 {
94                             return Err(1);
95                         }
96                         new.count -= 1;
97                     }
98                 }
99 
100                 if unsafe {
101                     try_cmpxchg_q(
102                         self as *mut LockRef as *mut usize as *mut u64,
103                         &mut old as *mut LockRef as *mut usize as *mut u64,
104                         &mut new as *mut LockRef as *mut usize as *mut u64,
105                     )
106                 } {
107                     // 无锁操作成功,返回新的值
108                     return Ok(new.count);
109                 }
110                 cpu_relax();
111             }
112         }
113 
114         return Err(SystemError::ETIMEDOUT.to_posix_errno());
115     }
116 
117     /// @brief 对于不支持无锁lockref的架构,直接返回Err(SystemError::EOPNOTSUPP_OR_ENOTSUP),表示不支持
118     #[cfg(not(target_arch = "x86_64"))]
119     #[inline]
cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32>120     fn cmpxchg_loop(&mut self, mode: CmpxchgMode) -> Result<i32, i32> {
121         use crate::include::bindings::bindings::EOPNOTSUPP_OR_ENOTSUP;
122 
123         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP.to_posix_errno());
124     }
125 
126     /// @brief 原子的将引用计数加1
inc(&mut self)127     pub fn inc(&mut self) {
128         let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::Increase);
129         if cmpxchg_result.is_ok() {
130             return;
131         }
132 
133         self.lock.lock();
134         self.count += 1;
135         self.lock.unlock();
136     }
137 
138     /**
139      * @brief 原子地将引用计数加1.如果原来的count≤0,则操作失败。
140      *
141      * @return Ok(self.count) 操作成功
142      * @return Err(SystemError::EPERM) 操作失败
143      */
inc_not_zero(&mut self) -> Result<i32, SystemError>144     pub fn inc_not_zero(&mut self) -> Result<i32, SystemError> {
145         {
146             let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::IncreaseNotZero);
147             if cmpxchg_result.is_ok() {
148                 return Ok(cmpxchg_result.unwrap());
149             } else if cmpxchg_result.unwrap_err() == 1 {
150                 // 不满足not zero 的条件
151                 return Err(SystemError::EPERM);
152             }
153         }
154         let mut retval = Err(SystemError::EPERM);
155         self.lock.lock();
156 
157         if self.count > 0 {
158             self.count += 1;
159             retval = Ok(self.count);
160         }
161 
162         self.lock.unlock();
163         return retval;
164     }
165 
166     /**
167      * @brief 引用计数自增1。(除非该lockref已经被标记为死亡)
168      *
169      * @return Ok(self.count) 操作成功
170      * @return Err(SystemError::EPERM) 操作失败,lockref已死亡
171      */
inc_not_dead(&mut self) -> Result<i32, SystemError>172     pub fn inc_not_dead(&mut self) -> Result<i32, SystemError> {
173         {
174             let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::IncreaseNotDead);
175             if cmpxchg_result.is_ok() {
176                 return Ok(cmpxchg_result.unwrap());
177             } else if cmpxchg_result.unwrap_err() == 1 {
178                 return Err(SystemError::EPERM);
179             }
180         }
181         // 快捷路径操作失败,尝试加锁
182         let mut retval = Err(SystemError::EPERM);
183 
184         self.lock.lock();
185         if self.count >= 0 {
186             self.count += 1;
187             retval = Ok(self.count);
188         }
189         self.lock.unlock();
190         return retval;
191     }
192 
193     /**
194      * @brief 原子地将引用计数-1。如果已处于count≤0的状态,则返回SystemError::EPERM
195      *
196      * 本函数与lockref_dec_return()的区别在于,当在cmpxchg()中检测到count<=0或已加锁,本函数会再次尝试通过加锁来执行操作
197      * 而后者会直接返回错误
198      *
199      * @return Ok(self.count) 操作成功,返回新的引用变量值
200      * @return Err(SystemError::EPERM) 操作失败,lockref处于count≤0的状态
201      */
dec(&mut self) -> Result<i32, SystemError>202     pub fn dec(&mut self) -> Result<i32, SystemError> {
203         {
204             let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::Decrease);
205             if cmpxchg_result.is_ok() {
206                 return Ok(cmpxchg_result.unwrap());
207             }
208         }
209         let retval: Result<i32, SystemError>;
210         self.lock.lock();
211 
212         if self.count > 0 {
213             self.count -= 1;
214             retval = Ok(self.count);
215         } else {
216             retval = Err(SystemError::EPERM);
217         }
218 
219         self.lock.unlock();
220 
221         return retval;
222     }
223 
224     /**
225      * @brief 原子地将引用计数减1。如果处于已加锁或count≤0的状态,则返回SystemError::EPERM
226      *      若当前处理器架构不支持cmpxchg,则退化为self.dec()
227      *
228      * 本函数与lockref_dec()的区别在于,当在cmpxchg()中检测到count<=0或已加锁,本函数会直接返回错误
229      * 而后者会再次尝试通过加锁来执行操作
230      *
231      * @return Ok(self.count) 操作成功,返回新的引用变量值
232      * @return Err(SystemError::EPERM) 操作失败,lockref处于已加锁或count≤0的状态
233      */
dec_return(&mut self) -> Result<i32, SystemError>234     pub fn dec_return(&mut self) -> Result<i32, SystemError> {
235         let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseReturn);
236         if cmpxchg_result.is_ok() {
237             return Ok(cmpxchg_result.unwrap());
238         } else if *cmpxchg_result.as_ref().unwrap_err() == 1 {
239             return Err(SystemError::EPERM);
240         }
241         // 由于cmpxchg超时,操作失败
242         if *cmpxchg_result.as_ref().unwrap_err()
243             != SystemError::EOPNOTSUPP_OR_ENOTSUP.to_posix_errno()
244         {
245             return Err(SystemError::EFAULT);
246         }
247 
248         // 能走到这里,代表架构当前不支持cmpxchg
249         // 退化为直接dec,加锁
250         return self.dec();
251     }
252 
253     /**
254      * @brief 原子地将引用计数减1。若当前的引用计数≤1,则操作失败
255      *
256      * 该函数与lockref_dec_or_lock_not_zero()的区别在于,当cmpxchg()时发现old.count≤1时,该函数会直接返回Err(SystemError::EPERM)
257      * 而后者在这种情况下,会尝试加锁来进行操作。
258      *
259      * @return Ok(self.count) 成功将引用计数减1
260      * @return Err(SystemError::EPERM) 如果当前的引用计数≤1,操作失败
261      */
dec_not_zero(&mut self) -> Result<i32, SystemError>262     pub fn dec_not_zero(&mut self) -> Result<i32, SystemError> {
263         {
264             let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseNotZero);
265             if cmpxchg_result.is_ok() {
266                 return Ok(cmpxchg_result.unwrap());
267             } else if cmpxchg_result.unwrap_err() == 1 {
268                 return Err(SystemError::EPERM);
269             }
270         }
271 
272         let retval: Result<i32, SystemError>;
273         self.lock.lock();
274         if self.count > 1 {
275             self.count -= 1;
276             retval = Ok(self.count);
277         } else {
278             retval = Err(SystemError::EPERM);
279         }
280         self.lock.unlock();
281         return retval;
282     }
283 
284     /**
285      * @brief 原子地将引用计数减1。若当前的引用计数≤1,则操作失败
286      *
287      * 该函数与lockref_dec_not_zero()的区别在于,当cmpxchg()时发现old.count≤1时,该函数会尝试加锁来进行操作。
288      * 而后者在这种情况下,会直接返回Err(SystemError::EPERM).
289      *
290      * @return Ok(self.count) 成功将引用计数减1
291      * @return Err(SystemError::EPERM) 如果当前的引用计数≤1,操作失败
292      */
dec_or_lock_not_zero(&mut self) -> Result<i32, SystemError>293     pub fn dec_or_lock_not_zero(&mut self) -> Result<i32, SystemError> {
294         {
295             let cmpxchg_result = self.cmpxchg_loop(CmpxchgMode::DecreaseOrLockNotZero);
296             if cmpxchg_result.is_ok() {
297                 return Ok(cmpxchg_result.unwrap());
298             }
299         }
300 
301         let retval: Result<i32, SystemError>;
302         self.lock.lock();
303         if self.count > 1 {
304             self.count -= 1;
305             retval = Ok(self.count);
306         } else {
307             retval = Err(SystemError::EPERM);
308         }
309         self.lock.unlock();
310         return retval;
311     }
312 
313     /**
314      * @brief 原子地将lockref变量标记为已经死亡(将count设置为负值)
315      */
mark_dead(&mut self)316     pub fn mark_dead(&mut self) {
317         self.lock.lock();
318         self.count = -128;
319         self.lock.unlock();
320     }
321 }
322 
323 /*
324 * 您可以使用以下代码测试lockref
325 
326    let mut lockref = LockRef::new();
327    kdebug!("lockref={:?}", lockref);
328    lockref.inc();
329    assert_eq!(lockref.count, 1);
330    kdebug!("lockref={:?}", lockref);
331    assert!(lockref.dec().is_ok());
332    assert_eq!(lockref.count, 0);
333 
334    assert!(lockref.dec().is_err());
335    assert_eq!(lockref.count, 0);
336 
337    lockref.inc();
338    assert_eq!(lockref.count, 1);
339 
340    assert!(lockref.dec_not_zero().is_err());
341 
342    lockref.inc();
343    assert_eq!(lockref.count, 2);
344 
345    assert!(lockref.dec_not_zero().is_ok());
346 
347    lockref.mark_dead();
348    assert!(lockref.count < 0);
349 
350    assert!(lockref.inc_not_dead().is_err());
351    kdebug!("lockref={:?}", lockref);
352 */
353