1 use alloc::{ 2 collections::LinkedList, 3 sync::{Arc, Weak}, 4 }; 5 use core::hash::{Hash, Hasher}; 6 use core::{ 7 intrinsics::{likely, unlikely}, 8 mem, 9 sync::atomic::AtomicU64, 10 }; 11 12 use hashbrown::HashMap; 13 use system_error::SystemError; 14 15 use crate::{ 16 arch::{CurrentIrqArch, MMArch}, 17 exception::InterruptArch, 18 libs::spinlock::{SpinLock, SpinLockGuard}, 19 mm::{ucontext::AddressSpace, MemoryManagementArch, VirtAddr}, 20 process::{Pid, ProcessControlBlock, ProcessManager}, 21 sched::{schedule, SchedMode}, 22 syscall::user_access::{UserBufferReader, UserBufferWriter}, 23 time::{ 24 timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, 25 TimeSpec, 26 }, 27 }; 28 29 use super::constant::*; 30 31 static mut FUTEX_DATA: Option<FutexData> = None; 32 33 pub struct FutexData { 34 data: SpinLock<HashMap<FutexKey, FutexHashBucket>>, 35 } 36 37 impl FutexData { 38 pub fn futex_map() -> SpinLockGuard<'static, HashMap<FutexKey, FutexHashBucket>> { 39 unsafe { FUTEX_DATA.as_ref().unwrap().data.lock() } 40 } 41 42 pub fn try_remove(key: &FutexKey) -> Option<FutexHashBucket> { 43 unsafe { 44 let mut guard = FUTEX_DATA.as_ref().unwrap().data.lock(); 45 if let Some(futex) = guard.get(key) { 46 if futex.chain.is_empty() { 47 return guard.remove(key); 48 } 49 } 50 } 51 None 52 } 53 } 54 55 pub struct Futex; 56 57 // 对于同一个futex的进程或线程将会在这个bucket等待 58 pub struct FutexHashBucket { 59 // 该futex维护的等待队列 60 chain: LinkedList<Arc<FutexObj>>, 61 } 62 63 impl FutexHashBucket { 64 /// ## 判断是否在bucket里 65 pub fn contains(&self, futex_q: &FutexObj) -> bool { 66 self.chain 67 .iter() 68 .filter(|x| futex_q.pcb.ptr_eq(&x.pcb) && x.key == futex_q.key) 69 .count() 70 != 0 71 } 72 73 /// 让futex_q在该bucket上挂起 74 /// 75 /// 进入该函数前,需要关中断 76 #[inline(always)] 77 pub fn sleep_no_sched(&mut self, futex_q: Arc<FutexObj>) -> Result<(), SystemError> { 78 assert!(!CurrentIrqArch::is_irq_enabled()); 79 self.chain.push_back(futex_q); 80 81 ProcessManager::mark_sleep(true)?; 82 83 Ok(()) 84 } 85 86 /// ## 唤醒队列中的最多nr_wake个进程 87 /// 88 /// return: 唤醒的进程数 89 #[inline(always)] 90 pub fn wake_up( 91 &mut self, 92 key: FutexKey, 93 bitset: Option<u32>, 94 nr_wake: u32, 95 ) -> Result<usize, SystemError> { 96 let mut count = 0; 97 let mut pop_count = 0; 98 while let Some(futex_q) = self.chain.pop_front() { 99 if futex_q.key == key { 100 // TODO: 考虑优先级继承的机制 101 102 if let Some(bitset) = bitset { 103 if futex_q.bitset != bitset { 104 self.chain.push_back(futex_q); 105 continue; 106 } 107 } 108 109 // 唤醒 110 if futex_q.pcb.upgrade().is_some() { 111 self.remove(futex_q.clone()); 112 ProcessManager::wakeup(&futex_q.pcb.upgrade().unwrap())?; 113 } 114 115 // 判断唤醒数 116 count += 1; 117 if count >= nr_wake { 118 break; 119 } 120 } else { 121 self.chain.push_back(futex_q); 122 } 123 // 判断是否循环完队列了 124 pop_count += 1; 125 if pop_count >= self.chain.len() { 126 break; 127 } 128 } 129 Ok(count as usize) 130 } 131 132 /// 将FutexObj从bucket中删除 133 pub fn remove(&mut self, futex: Arc<FutexObj>) { 134 self.chain 135 .extract_if(|x| Arc::ptr_eq(x, &futex)) 136 .for_each(drop); 137 } 138 } 139 140 #[derive(Debug)] 141 pub struct FutexObj { 142 pcb: Weak<ProcessControlBlock>, 143 key: FutexKey, 144 bitset: u32, 145 // TODO: 优先级继承 146 } 147 148 pub enum FutexAccess { 149 FutexRead, 150 FutexWrite, 151 } 152 153 #[allow(dead_code)] 154 #[derive(Hash, PartialEq, Eq, Clone, Debug)] 155 /// ### 用于定位内核唯一的futex 156 pub enum InnerFutexKey { 157 Shared(SharedKey), 158 Private(PrivateKey), 159 } 160 161 #[derive(Hash, PartialEq, Eq, Clone, Debug)] 162 pub struct FutexKey { 163 ptr: u64, 164 word: u64, 165 offset: u32, 166 key: InnerFutexKey, 167 } 168 169 /// 不同进程间通过文件共享futex变量,表明该变量在文件中的位置 170 #[derive(Hash, PartialEq, Eq, Clone, Debug)] 171 pub struct SharedKey { 172 i_seq: u64, 173 page_offset: u64, 174 } 175 176 /// 同一进程的不同线程共享futex变量,表明该变量在进程地址空间中的位置 177 #[derive(Clone, Debug)] 178 pub struct PrivateKey { 179 // 所在的地址空间 180 address_space: Option<Weak<AddressSpace>>, 181 // 表示所在页面的初始地址 182 address: u64, 183 } 184 185 impl Hash for PrivateKey { 186 fn hash<H: Hasher>(&self, state: &mut H) { 187 self.address.hash(state); 188 } 189 } 190 191 impl Eq for PrivateKey {} 192 193 impl PartialEq for PrivateKey { 194 fn eq(&self, other: &Self) -> bool { 195 if self.address_space.is_none() && other.address_space.is_none() { 196 return self.address == other.address; 197 } else { 198 return self 199 .address_space 200 .as_ref() 201 .unwrap_or(&Weak::default()) 202 .ptr_eq(other.address_space.as_ref().unwrap_or(&Weak::default())) 203 && self.address == other.address; 204 } 205 } 206 } 207 208 impl Futex { 209 /// ### 初始化FUTEX_DATA 210 pub fn init() { 211 unsafe { 212 FUTEX_DATA = Some(FutexData { 213 data: SpinLock::new(HashMap::new()), 214 }) 215 }; 216 } 217 218 /// ### 让当前进程在指定futex上等待直到futex_wake显式唤醒 219 pub fn futex_wait( 220 uaddr: VirtAddr, 221 flags: FutexFlag, 222 val: u32, 223 abs_time: Option<TimeSpec>, 224 bitset: u32, 225 ) -> Result<usize, SystemError> { 226 if bitset == 0 { 227 return Err(SystemError::EINVAL); 228 } 229 230 // 获取全局hash表的key值 231 let key = Self::get_futex_key( 232 uaddr, 233 flags.contains(FutexFlag::FLAGS_SHARED), 234 FutexAccess::FutexRead, 235 )?; 236 237 let mut futex_map_guard = FutexData::futex_map(); 238 let bucket = futex_map_guard.get_mut(&key); 239 let bucket_mut = match bucket { 240 Some(bucket) => bucket, 241 None => { 242 let bucket = FutexHashBucket { 243 chain: LinkedList::new(), 244 }; 245 futex_map_guard.insert(key.clone(), bucket); 246 futex_map_guard.get_mut(&key).unwrap() 247 } 248 }; 249 250 // 使用UserBuffer读取futex 251 let user_reader = 252 UserBufferReader::new(uaddr.as_ptr::<u32>(), core::mem::size_of::<u32>(), true)?; 253 254 // 从用户空间读取到futex的val 255 let mut uval = 0; 256 257 // 读取 258 // 这里只尝试一种方式去读取用户空间,与linux不太一致 259 // 对于linux,如果bucket被锁住时读取失败,将会将bucket解锁后重新读取 260 user_reader.copy_one_from_user::<u32>(&mut uval, 0)?; 261 262 // 不满足wait条件,返回错误 263 if uval != val { 264 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 265 } 266 267 let pcb = ProcessManager::current_pcb(); 268 // 创建超时计时器任务 269 let mut timer = None; 270 if let Some(time) = abs_time { 271 let wakeup_helper = WakeUpHelper::new(pcb.clone()); 272 273 let sec = time.tv_sec; 274 let nsec = time.tv_nsec; 275 let jiffies = next_n_us_timer_jiffies((nsec / 1000 + sec * 1_000_000) as u64); 276 277 let wake_up = Timer::new(wakeup_helper, jiffies); 278 279 wake_up.activate(); 280 timer = Some(wake_up); 281 } 282 283 let futex_q = Arc::new(FutexObj { 284 pcb: Arc::downgrade(&pcb), 285 key: key.clone(), 286 bitset, 287 }); 288 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 289 // 满足条件则将当前进程在该bucket上挂起 290 bucket_mut.sleep_no_sched(futex_q.clone()).map_err(|e| { 291 kwarn!("error:{e:?}"); 292 e 293 })?; 294 drop(futex_map_guard); 295 drop(irq_guard); 296 schedule(SchedMode::SM_NONE); 297 298 // 被唤醒后的检查 299 let mut futex_map_guard = FutexData::futex_map(); 300 let bucket = futex_map_guard.get_mut(&key); 301 let bucket_mut = match bucket { 302 // 如果该pcb不在链表里面了或者该链表已经被释放,就证明是正常的Wake操作 303 Some(bucket_mut) => { 304 if !bucket_mut.contains(&futex_q) { 305 // 取消定时器任务 306 if let Some(timer) = timer { 307 timer.cancel(); 308 } 309 return Ok(0); 310 } 311 // 非正常唤醒,返回交给下层 312 bucket_mut 313 } 314 None => { 315 // 取消定时器任务 316 if let Some(timer) = timer { 317 timer.cancel(); 318 } 319 return Ok(0); 320 } 321 }; 322 323 // 如果是超时唤醒,则返回错误 324 if timer.is_some() && timer.clone().unwrap().timeout() { 325 bucket_mut.remove(futex_q); 326 327 return Err(SystemError::ETIMEDOUT); 328 } 329 330 // TODO: 如果没有挂起的信号,则重新判断是否满足wait要求,重新进入wait 331 332 // 经过前面的几个判断,到这里之后, 333 // 当前进程被唤醒大概率是其他进程更改了uval,需要重新去判断当前进程是否满足wait 334 335 // 到这里之后,前面的唤醒条件都不满足,则是被信号唤醒 336 // 需要处理信号然后重启futex系统调用 337 338 // 取消定时器任务 339 if let Some(timer) = timer { 340 if !timer.timeout() { 341 timer.cancel(); 342 } 343 } 344 345 Ok(0) 346 } 347 348 // ### 唤醒指定futex上挂起的最多nr_wake个进程 349 pub fn futex_wake( 350 uaddr: VirtAddr, 351 flags: FutexFlag, 352 nr_wake: u32, 353 bitset: u32, 354 ) -> Result<usize, SystemError> { 355 if bitset == 0 { 356 return Err(SystemError::EINVAL); 357 } 358 359 // 获取futex_key,并且判断地址空间合法性 360 let key = Self::get_futex_key( 361 uaddr, 362 flags.contains(FutexFlag::FLAGS_SHARED), 363 FutexAccess::FutexRead, 364 )?; 365 let mut binding = FutexData::futex_map(); 366 let bucket_mut = binding.get_mut(&key).ok_or(SystemError::EINVAL)?; 367 368 // 确保后面的唤醒操作是有意义的 369 if bucket_mut.chain.is_empty() { 370 return Ok(0); 371 } 372 // 从队列中唤醒 373 let count = bucket_mut.wake_up(key.clone(), Some(bitset), nr_wake)?; 374 375 drop(binding); 376 377 FutexData::try_remove(&key); 378 379 Ok(count) 380 } 381 382 /// ### 唤醒制定uaddr1上的最多nr_wake个进程,然后将uaddr1最多nr_requeue个进程移动到uaddr2绑定的futex上 383 pub fn futex_requeue( 384 uaddr1: VirtAddr, 385 flags: FutexFlag, 386 uaddr2: VirtAddr, 387 nr_wake: i32, 388 nr_requeue: i32, 389 cmpval: Option<u32>, 390 requeue_pi: bool, 391 ) -> Result<usize, SystemError> { 392 if nr_requeue < 0 || nr_wake < 0 { 393 return Err(SystemError::EINVAL); 394 } 395 396 // 暂时不支持优先级继承 397 if requeue_pi { 398 return Err(SystemError::ENOSYS); 399 } 400 401 let key1 = Self::get_futex_key( 402 uaddr1, 403 flags.contains(FutexFlag::FLAGS_SHARED), 404 FutexAccess::FutexRead, 405 )?; 406 let key2 = Self::get_futex_key(uaddr2, flags.contains(FutexFlag::FLAGS_SHARED), { 407 match requeue_pi { 408 true => FutexAccess::FutexWrite, 409 false => FutexAccess::FutexRead, 410 } 411 })?; 412 413 if requeue_pi && key1 == key2 { 414 return Err(SystemError::EINVAL); 415 } 416 417 if likely(cmpval.is_some()) { 418 let uval_reader = 419 UserBufferReader::new(uaddr1.as_ptr::<u32>(), core::mem::size_of::<u32>(), true)?; 420 let curval = uval_reader.read_one_from_user::<u32>(0)?; 421 422 // 判断是否满足条件 423 if *curval != cmpval.unwrap() { 424 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 425 } 426 } 427 428 let mut futex_data_guard = FutexData::futex_map(); 429 if !requeue_pi { 430 // 唤醒nr_wake个进程 431 let bucket_1_mut = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?; 432 let ret = bucket_1_mut.wake_up(key1.clone(), None, nr_wake as u32)?; 433 // 将bucket1中最多nr_requeue个任务转移到bucket2 434 for _ in 0..nr_requeue { 435 let bucket_1_mut = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?; 436 let futex_q = bucket_1_mut.chain.pop_front(); 437 match futex_q { 438 Some(futex_q) => { 439 let bucket_2_mut = 440 futex_data_guard.get_mut(&key2).ok_or(SystemError::EINVAL)?; 441 bucket_2_mut.chain.push_back(futex_q); 442 } 443 None => { 444 break; 445 } 446 } 447 } 448 449 return Ok(ret); 450 } else { 451 // 暂时不支持优先级继承 452 todo!() 453 } 454 } 455 456 /// ### 唤醒futex上的进程的同时进行一些操作 457 pub fn futex_wake_op( 458 uaddr1: VirtAddr, 459 flags: FutexFlag, 460 uaddr2: VirtAddr, 461 nr_wake: i32, 462 nr_wake2: i32, 463 op: i32, 464 ) -> Result<usize, SystemError> { 465 let key1 = Futex::get_futex_key( 466 uaddr1, 467 flags.contains(FutexFlag::FLAGS_SHARED), 468 FutexAccess::FutexRead, 469 )?; 470 let key2 = Futex::get_futex_key( 471 uaddr2, 472 flags.contains(FutexFlag::FLAGS_SHARED), 473 FutexAccess::FutexWrite, 474 )?; 475 476 let mut futex_data_guard = FutexData::futex_map(); 477 let bucket1 = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?; 478 let mut wake_count = 0; 479 480 // 唤醒uaddr1中的进程 481 wake_count += bucket1.wake_up(key1, None, nr_wake as u32)?; 482 483 match Self::futex_atomic_op_inuser(op as u32, uaddr2) { 484 Ok(ret) => { 485 // 操作成功则唤醒uaddr2中的进程 486 if ret { 487 let bucket2 = futex_data_guard.get_mut(&key2).ok_or(SystemError::EINVAL)?; 488 wake_count += bucket2.wake_up(key2, None, nr_wake2 as u32)?; 489 } 490 } 491 Err(e) => { 492 // TODO:retry? 493 return Err(e); 494 } 495 } 496 497 Ok(wake_count) 498 } 499 500 fn get_futex_key( 501 uaddr: VirtAddr, 502 fshared: bool, 503 _access: FutexAccess, 504 ) -> Result<FutexKey, SystemError> { 505 let mut address = uaddr.data(); 506 507 // 计算相对页的偏移量 508 let offset = address & (MMArch::PAGE_SIZE - 1); 509 // 判断内存对齐 510 if uaddr.data() & (core::mem::size_of::<u32>() - 1) != 0 { 511 return Err(SystemError::EINVAL); 512 } 513 514 // 目前address指向所在页面的起始地址 515 address -= offset; 516 517 // 若不是进程间共享的futex,则返回Private 518 if !fshared { 519 return Ok(FutexKey { 520 ptr: 0, 521 word: 0, 522 offset: offset as u32, 523 key: InnerFutexKey::Private(PrivateKey { 524 address: address as u64, 525 address_space: None, 526 }), 527 }); 528 } 529 530 // 获取到地址所在地址空间 531 let address_space = AddressSpace::current()?; 532 // TODO: 判断是否为匿名映射,是匿名映射才返回PrivateKey 533 return Ok(FutexKey { 534 ptr: 0, 535 word: 0, 536 offset: offset as u32, 537 key: InnerFutexKey::Private(PrivateKey { 538 address: address as u64, 539 address_space: Some(Arc::downgrade(&address_space)), 540 }), 541 }); 542 543 // 未实现共享内存机制,贡献内存部分应该通过inode构建SharedKey 544 // todo!("Shared memory not implemented"); 545 } 546 547 pub fn futex_atomic_op_inuser(encoded_op: u32, uaddr: VirtAddr) -> Result<bool, SystemError> { 548 let op = FutexOP::from_bits((encoded_op & 0x70000000) >> 28).ok_or(SystemError::ENOSYS)?; 549 let cmp = 550 FutexOpCMP::from_bits((encoded_op & 0x0f000000) >> 24).ok_or(SystemError::ENOSYS)?; 551 552 let sign_extend32 = |value: u32, index: i32| { 553 let shift = (31 - index) as u8; 554 return (value << shift) >> shift; 555 }; 556 557 let mut oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 11); 558 let cmparg = sign_extend32(encoded_op & 0x00000fff, 11); 559 560 if (encoded_op & (FutexOP::FUTEX_OP_OPARG_SHIFT.bits() << 28) != 0) && oparg > 31 { 561 kwarn!( 562 "futex_wake_op: pid:{} tries to shift op by {}; fix this program", 563 ProcessManager::current_pcb().pid().data(), 564 oparg 565 ); 566 567 oparg &= 31; 568 } 569 570 // TODO: 这个汇编似乎是有问题的,目前不好测试 571 let old_val = Self::arch_futex_atomic_op_inuser(op, oparg, uaddr)?; 572 573 match cmp { 574 FutexOpCMP::FUTEX_OP_CMP_EQ => { 575 return Ok(cmparg == old_val); 576 } 577 FutexOpCMP::FUTEX_OP_CMP_NE => { 578 return Ok(cmparg != old_val); 579 } 580 FutexOpCMP::FUTEX_OP_CMP_LT => { 581 return Ok(cmparg < old_val); 582 } 583 FutexOpCMP::FUTEX_OP_CMP_LE => { 584 return Ok(cmparg <= old_val); 585 } 586 FutexOpCMP::FUTEX_OP_CMP_GE => { 587 return Ok(cmparg >= old_val); 588 } 589 FutexOpCMP::FUTEX_OP_CMP_GT => { 590 return Ok(cmparg > old_val); 591 } 592 _ => { 593 return Err(SystemError::ENOSYS); 594 } 595 } 596 } 597 598 /// ### 对futex进行操作 599 /// 600 /// 进入该方法会关闭中断保证修改的原子性,所以进入该方法前应确保中断锁已释放 601 /// 602 /// ### return uaddr原来的值 603 #[allow(unused_assignments)] 604 pub fn arch_futex_atomic_op_inuser( 605 op: FutexOP, 606 oparg: u32, 607 uaddr: VirtAddr, 608 ) -> Result<u32, SystemError> { 609 let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 610 611 let reader = 612 UserBufferReader::new(uaddr.as_ptr::<u32>(), core::mem::size_of::<u32>(), true)?; 613 614 let oldval = reader.read_one_from_user::<u32>(0)?; 615 616 let atomic_addr = AtomicU64::new(uaddr.data() as u64); 617 // 这个指针是指向指针的指针 618 let ptr = atomic_addr.as_ptr(); 619 match op { 620 FutexOP::FUTEX_OP_SET => unsafe { 621 *((*ptr) as *mut u32) = oparg; 622 }, 623 FutexOP::FUTEX_OP_ADD => unsafe { 624 *((*ptr) as *mut u32) += oparg; 625 }, 626 FutexOP::FUTEX_OP_OR => unsafe { 627 *((*ptr) as *mut u32) |= oparg; 628 }, 629 FutexOP::FUTEX_OP_ANDN => unsafe { 630 *((*ptr) as *mut u32) &= oparg; 631 }, 632 FutexOP::FUTEX_OP_XOR => unsafe { 633 *((*ptr) as *mut u32) ^= oparg; 634 }, 635 _ => return Err(SystemError::ENOSYS), 636 } 637 638 drop(guard); 639 640 Ok(*oldval) 641 } 642 } 643 644 //用于指示在处理robust list是最多处理多少个条目 645 const ROBUST_LIST_LIMIT: isize = 2048; 646 647 #[derive(Debug, Copy, Clone)] 648 pub struct RobustList { 649 next: VirtAddr, 650 } 651 652 #[derive(Debug, Copy, Clone)] 653 pub struct RobustListHead { 654 list: RobustList, 655 futex_offset: isize, 656 list_op_pending: VirtAddr, 657 } 658 659 impl RobustListHead { 660 /// # 获得futex的用户空间地址 661 pub fn futex_uaddr(&self, entry: VirtAddr) -> VirtAddr { 662 return VirtAddr::new(entry.data() + self.futex_offset as usize); 663 } 664 665 /// #获得list_op_peding的用户空间地址 666 pub fn pending_uaddr(&self) -> Option<VirtAddr> { 667 if self.list_op_pending.is_null() { 668 return None; 669 } else { 670 return Some(self.futex_uaddr(self.list_op_pending)); 671 } 672 } 673 674 /// # 在内核注册robust list 675 /// ## 参数 676 /// - head_uaddr:robust list head用户空间地址 677 /// - len:robust list head的长度 678 pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result<usize, SystemError> { 679 let robust_list_head_len = mem::size_of::<&RobustListHead>(); 680 if unlikely(len != robust_list_head_len) { 681 return Err(SystemError::EINVAL); 682 } 683 684 let user_buffer_reader = UserBufferReader::new( 685 head_uaddr.as_ptr::<RobustListHead>(), 686 mem::size_of::<RobustListHead>(), 687 true, 688 )?; 689 let robust_list_head = *user_buffer_reader.read_one_from_user::<RobustListHead>(0)?; 690 691 // 向内核注册robust list 692 ProcessManager::current_pcb().set_robust_list(Some(robust_list_head)); 693 694 return Ok(0); 695 } 696 697 /// # 获取robust list head到用户空间 698 /// ## 参数 699 /// - pid:当前进程/线程的pid 700 /// - 701 pub fn get_robust_list( 702 pid: usize, 703 head_uaddr: VirtAddr, 704 len_ptr_uaddr: VirtAddr, 705 ) -> Result<usize, SystemError> { 706 // 获取当前进程的process control block 707 let pcb: Arc<ProcessControlBlock> = if pid == 0 { 708 ProcessManager::current_pcb() 709 } else { 710 ProcessManager::find(Pid::new(pid)).ok_or(SystemError::ESRCH)? 711 }; 712 713 // TODO: 检查当前进程是否能ptrace另一个进程 714 let ptrace = true; 715 if !ptrace { 716 return Err(SystemError::EPERM); 717 } 718 719 //获取当前线程的robust list head 和 长度 720 let robust_list_head = (*pcb.get_robust_list()).ok_or(SystemError::EINVAL)?; 721 722 // 将len拷贝到用户空间len_ptr 723 let mut user_writer = UserBufferWriter::new( 724 len_ptr_uaddr.as_ptr::<usize>(), 725 core::mem::size_of::<usize>(), 726 true, 727 )?; 728 user_writer.copy_one_to_user(&mem::size_of::<RobustListHead>(), 0)?; 729 // 将head拷贝到用户空间head 730 let mut user_writer = UserBufferWriter::new( 731 head_uaddr.as_ptr::<RobustListHead>(), 732 mem::size_of::<RobustListHead>(), 733 true, 734 )?; 735 user_writer.copy_one_to_user(&robust_list_head, 0)?; 736 737 return Ok(0); 738 } 739 740 /// # 进程/线程退出时清理工作 741 /// ## 参数 742 /// - current:当前进程/线程的pcb 743 /// - pid:当前进程/线程的pid 744 pub fn exit_robust_list(pcb: Arc<ProcessControlBlock>) { 745 //指向当前进程的robust list头部的指针 746 let head = match *pcb.get_robust_list() { 747 Some(rl) => rl, 748 None => { 749 return; 750 } 751 }; 752 // 遍历当前进程/线程的robust list 753 for futex_uaddr in head.futexes() { 754 let ret = Self::handle_futex_death(futex_uaddr, pcb.pid().into() as u32); 755 if ret.is_err() { 756 return; 757 } 758 } 759 pcb.set_robust_list(None); 760 } 761 762 /// # 返回robust list的迭代器,将robust list list_op_pending 放到最后(如果存在) 763 fn futexes(&self) -> FutexIterator<'_> { 764 return FutexIterator::new(self); 765 } 766 767 /// # 处理进程即将死亡时,进程已经持有的futex,唤醒其他等待该futex的线程 768 /// ## 参数 769 /// - futex_uaddr:futex的用户空间地址 770 /// - pid: 当前进程/线程的pid 771 fn handle_futex_death(futex_uaddr: VirtAddr, pid: u32) -> Result<usize, SystemError> { 772 let futex_val = { 773 if futex_uaddr.is_null() { 774 return Err(SystemError::EINVAL); 775 } 776 let user_buffer_reader = UserBufferReader::new( 777 futex_uaddr.as_ptr::<u32>(), 778 core::mem::size_of::<u32>(), 779 true, 780 )?; 781 *user_buffer_reader.read_one_from_user::<u32>(0)? 782 }; 783 784 let mut uval = futex_val; 785 loop { 786 // 该futex可能被其他进程占有 787 let owner = uval & FUTEX_TID_MASK; 788 if owner != pid { 789 break; 790 } 791 792 // 判断是否有FUTEX_WAITERS和标记FUTEX_OWNER_DIED 793 let mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; 794 795 // 读取用户空间目前的futex字段,判断在此之前futex是否有被修改 796 let user_buffer_reader = UserBufferReader::new( 797 futex_uaddr.as_ptr::<u32>(), 798 core::mem::size_of::<u32>(), 799 true, 800 )?; 801 let nval = *user_buffer_reader.read_one_from_user::<u32>(0)?; 802 if nval != mval { 803 uval = nval; 804 let mut user_buffer_writer = UserBufferWriter::new( 805 futex_uaddr.as_ptr::<u32>(), 806 core::mem::size_of::<u32>(), 807 true, 808 )?; 809 user_buffer_writer.copy_one_to_user(&mval, 0)?; 810 continue; 811 } 812 813 // 有等待者,进行唤醒操作 814 if nval & FUTEX_WAITERS != 0 { 815 let mut flags = FutexFlag::FLAGS_MATCH_NONE; 816 flags.insert(FutexFlag::FLAGS_SHARED); 817 Futex::futex_wake(futex_uaddr, flags, 1, FUTEX_BITSET_MATCH_ANY)?; 818 } 819 break; 820 } 821 822 return Ok(0); 823 } 824 } 825 826 pub struct FutexIterator<'a> { 827 robust_list_head: &'a RobustListHead, 828 entry: VirtAddr, 829 count: isize, 830 } 831 832 impl<'a> FutexIterator<'a> { 833 pub fn new(robust_list_head: &'a RobustListHead) -> Self { 834 return Self { 835 robust_list_head, 836 entry: robust_list_head.list.next, 837 count: 0, 838 }; 839 } 840 841 fn is_end(&mut self) -> bool { 842 return self.count < 0; 843 } 844 } 845 846 impl<'a> Iterator for FutexIterator<'a> { 847 type Item = VirtAddr; 848 849 fn next(&mut self) -> Option<Self::Item> { 850 if self.is_end() { 851 return None; 852 } 853 854 while self.entry.data() != &self.robust_list_head.list as *const RobustList as usize { 855 if self.count == ROBUST_LIST_LIMIT { 856 break; 857 } 858 if self.entry.is_null() { 859 return None; 860 } 861 862 //获取futex val地址 863 let futex_uaddr = if self.entry.data() != self.robust_list_head.list_op_pending.data() { 864 Some(self.robust_list_head.futex_uaddr(self.entry)) 865 } else { 866 None 867 }; 868 869 let user_buffer_reader = UserBufferReader::new( 870 self.entry.as_ptr::<RobustList>(), 871 mem::size_of::<RobustList>(), 872 true, 873 ) 874 .ok()?; 875 let next_entry = user_buffer_reader 876 .read_one_from_user::<RobustList>(0) 877 .ok()?; 878 879 self.entry = next_entry.next; 880 881 self.count += 1; 882 883 if futex_uaddr.is_some() { 884 return futex_uaddr; 885 } 886 } 887 self.count -= 1; 888 self.robust_list_head.pending_uaddr() 889 } 890 } 891