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