1*971462beSGnoCiYeH use alloc::{ 2*971462beSGnoCiYeH collections::LinkedList, 3*971462beSGnoCiYeH sync::{Arc, Weak}, 4*971462beSGnoCiYeH }; 5*971462beSGnoCiYeH use core::hash::{Hash, Hasher}; 6*971462beSGnoCiYeH use core::{intrinsics::likely, sync::atomic::AtomicU64}; 7*971462beSGnoCiYeH use hashbrown::HashMap; 8*971462beSGnoCiYeH 9*971462beSGnoCiYeH use crate::{ 10*971462beSGnoCiYeH arch::{sched::sched, CurrentIrqArch, MMArch}, 11*971462beSGnoCiYeH exception::InterruptArch, 12*971462beSGnoCiYeH libs::spinlock::{SpinLock, SpinLockGuard}, 13*971462beSGnoCiYeH mm::{ucontext::AddressSpace, MemoryManagementArch, VirtAddr}, 14*971462beSGnoCiYeH process::{ProcessControlBlock, ProcessManager}, 15*971462beSGnoCiYeH syscall::{user_access::UserBufferReader, SystemError}, 16*971462beSGnoCiYeH time::{ 17*971462beSGnoCiYeH timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, 18*971462beSGnoCiYeH TimeSpec, 19*971462beSGnoCiYeH }, 20*971462beSGnoCiYeH }; 21*971462beSGnoCiYeH 22*971462beSGnoCiYeH use super::constant::*; 23*971462beSGnoCiYeH 24*971462beSGnoCiYeH static mut FUTEX_DATA: Option<FutexData> = None; 25*971462beSGnoCiYeH 26*971462beSGnoCiYeH pub struct FutexData { 27*971462beSGnoCiYeH data: SpinLock<HashMap<FutexKey, FutexHashBucket>>, 28*971462beSGnoCiYeH } 29*971462beSGnoCiYeH 30*971462beSGnoCiYeH impl FutexData { 31*971462beSGnoCiYeH pub fn futex_map() -> SpinLockGuard<'static, HashMap<FutexKey, FutexHashBucket>> { 32*971462beSGnoCiYeH unsafe { FUTEX_DATA.as_ref().unwrap().data.lock() } 33*971462beSGnoCiYeH } 34*971462beSGnoCiYeH 35*971462beSGnoCiYeH pub fn try_remove(key: &FutexKey) -> Option<FutexHashBucket> { 36*971462beSGnoCiYeH unsafe { 37*971462beSGnoCiYeH let mut guard = FUTEX_DATA.as_ref().unwrap().data.lock(); 38*971462beSGnoCiYeH if let Some(futex) = guard.get(key) { 39*971462beSGnoCiYeH if futex.chain.is_empty() { 40*971462beSGnoCiYeH return guard.remove(key); 41*971462beSGnoCiYeH } 42*971462beSGnoCiYeH } 43*971462beSGnoCiYeH } 44*971462beSGnoCiYeH None 45*971462beSGnoCiYeH } 46*971462beSGnoCiYeH } 47*971462beSGnoCiYeH 48*971462beSGnoCiYeH pub struct Futex; 49*971462beSGnoCiYeH 50*971462beSGnoCiYeH // 对于同一个futex的进程或线程将会在这个bucket等待 51*971462beSGnoCiYeH pub struct FutexHashBucket { 52*971462beSGnoCiYeH // 该futex维护的等待队列 53*971462beSGnoCiYeH chain: LinkedList<Arc<FutexObj>>, 54*971462beSGnoCiYeH } 55*971462beSGnoCiYeH 56*971462beSGnoCiYeH impl FutexHashBucket { 57*971462beSGnoCiYeH /// ## 判断是否在bucket里 58*971462beSGnoCiYeH pub fn contains(&self, futex_q: &FutexObj) -> bool { 59*971462beSGnoCiYeH self.chain 60*971462beSGnoCiYeH .iter() 61*971462beSGnoCiYeH .filter(|x| futex_q.pcb.ptr_eq(&x.pcb) && x.key == futex_q.key) 62*971462beSGnoCiYeH .count() 63*971462beSGnoCiYeH != 0 64*971462beSGnoCiYeH } 65*971462beSGnoCiYeH 66*971462beSGnoCiYeH /// 让futex_q在该bucket上挂起 67*971462beSGnoCiYeH /// 68*971462beSGnoCiYeH /// 进入该函数前,需要关中断 69*971462beSGnoCiYeH #[inline(always)] 70*971462beSGnoCiYeH pub fn sleep_no_sched(&mut self, futex_q: Arc<FutexObj>) -> Result<(), SystemError> { 71*971462beSGnoCiYeH assert!(CurrentIrqArch::is_irq_enabled() == false); 72*971462beSGnoCiYeH self.chain.push_back(futex_q); 73*971462beSGnoCiYeH 74*971462beSGnoCiYeH ProcessManager::mark_sleep(true)?; 75*971462beSGnoCiYeH 76*971462beSGnoCiYeH Ok(()) 77*971462beSGnoCiYeH } 78*971462beSGnoCiYeH 79*971462beSGnoCiYeH /// ## 唤醒队列中的最多nr_wake个进程 80*971462beSGnoCiYeH /// 81*971462beSGnoCiYeH /// return: 唤醒的进程数 82*971462beSGnoCiYeH #[inline(always)] 83*971462beSGnoCiYeH pub fn wake_up( 84*971462beSGnoCiYeH &mut self, 85*971462beSGnoCiYeH key: FutexKey, 86*971462beSGnoCiYeH bitset: Option<u32>, 87*971462beSGnoCiYeH nr_wake: u32, 88*971462beSGnoCiYeH ) -> Result<usize, SystemError> { 89*971462beSGnoCiYeH let mut count = 0; 90*971462beSGnoCiYeH let mut pop_count = 0; 91*971462beSGnoCiYeH while let Some(futex_q) = self.chain.pop_front() { 92*971462beSGnoCiYeH if futex_q.key == key { 93*971462beSGnoCiYeH // TODO: 考虑优先级继承的机制 94*971462beSGnoCiYeH 95*971462beSGnoCiYeH if let Some(bitset) = bitset { 96*971462beSGnoCiYeH if futex_q.bitset != bitset { 97*971462beSGnoCiYeH self.chain.push_back(futex_q); 98*971462beSGnoCiYeH continue; 99*971462beSGnoCiYeH } 100*971462beSGnoCiYeH } 101*971462beSGnoCiYeH 102*971462beSGnoCiYeH // 唤醒 103*971462beSGnoCiYeH if futex_q.pcb.upgrade().is_some() { 104*971462beSGnoCiYeH self.remove(futex_q.clone()); 105*971462beSGnoCiYeH ProcessManager::wakeup(&futex_q.pcb.upgrade().unwrap())?; 106*971462beSGnoCiYeH } 107*971462beSGnoCiYeH 108*971462beSGnoCiYeH // 判断唤醒数 109*971462beSGnoCiYeH count += 1; 110*971462beSGnoCiYeH if count >= nr_wake { 111*971462beSGnoCiYeH break; 112*971462beSGnoCiYeH } 113*971462beSGnoCiYeH } else { 114*971462beSGnoCiYeH self.chain.push_back(futex_q); 115*971462beSGnoCiYeH } 116*971462beSGnoCiYeH // 判断是否循环完队列了 117*971462beSGnoCiYeH pop_count += 1; 118*971462beSGnoCiYeH if pop_count >= self.chain.len() { 119*971462beSGnoCiYeH break; 120*971462beSGnoCiYeH } 121*971462beSGnoCiYeH } 122*971462beSGnoCiYeH Ok(count as usize) 123*971462beSGnoCiYeH } 124*971462beSGnoCiYeH 125*971462beSGnoCiYeH /// 将FutexObj从bucket中删除 126*971462beSGnoCiYeH pub fn remove(&mut self, futex: Arc<FutexObj>) { 127*971462beSGnoCiYeH self.chain.drain_filter(|x| Arc::ptr_eq(x, &futex)); 128*971462beSGnoCiYeH } 129*971462beSGnoCiYeH } 130*971462beSGnoCiYeH 131*971462beSGnoCiYeH #[derive(Debug)] 132*971462beSGnoCiYeH pub struct FutexObj { 133*971462beSGnoCiYeH pcb: Weak<ProcessControlBlock>, 134*971462beSGnoCiYeH key: FutexKey, 135*971462beSGnoCiYeH bitset: u32, 136*971462beSGnoCiYeH // TODO: 优先级继承 137*971462beSGnoCiYeH } 138*971462beSGnoCiYeH 139*971462beSGnoCiYeH pub enum FutexAccess { 140*971462beSGnoCiYeH FutexRead, 141*971462beSGnoCiYeH FutexWrite, 142*971462beSGnoCiYeH } 143*971462beSGnoCiYeH 144*971462beSGnoCiYeH #[allow(dead_code)] 145*971462beSGnoCiYeH #[derive(Hash, PartialEq, Eq, Clone, Debug)] 146*971462beSGnoCiYeH /// ### 用于定位内核唯一的futex 147*971462beSGnoCiYeH pub enum InnerFutexKey { 148*971462beSGnoCiYeH Shared(SharedKey), 149*971462beSGnoCiYeH Private(PrivateKey), 150*971462beSGnoCiYeH } 151*971462beSGnoCiYeH 152*971462beSGnoCiYeH #[derive(Hash, PartialEq, Eq, Clone, Debug)] 153*971462beSGnoCiYeH pub struct FutexKey { 154*971462beSGnoCiYeH ptr: u64, 155*971462beSGnoCiYeH word: u64, 156*971462beSGnoCiYeH offset: u32, 157*971462beSGnoCiYeH key: InnerFutexKey, 158*971462beSGnoCiYeH } 159*971462beSGnoCiYeH 160*971462beSGnoCiYeH /// 不同进程间通过文件共享futex变量,表明该变量在文件中的位置 161*971462beSGnoCiYeH #[derive(Hash, PartialEq, Eq, Clone, Debug)] 162*971462beSGnoCiYeH pub struct SharedKey { 163*971462beSGnoCiYeH i_seq: u64, 164*971462beSGnoCiYeH page_offset: u64, 165*971462beSGnoCiYeH } 166*971462beSGnoCiYeH 167*971462beSGnoCiYeH /// 同一进程的不同线程共享futex变量,表明该变量在进程地址空间中的位置 168*971462beSGnoCiYeH #[derive(Clone, Debug)] 169*971462beSGnoCiYeH pub struct PrivateKey { 170*971462beSGnoCiYeH // 所在的地址空间 171*971462beSGnoCiYeH address_space: Option<Weak<AddressSpace>>, 172*971462beSGnoCiYeH // 表示所在页面的初始地址 173*971462beSGnoCiYeH address: u64, 174*971462beSGnoCiYeH } 175*971462beSGnoCiYeH 176*971462beSGnoCiYeH impl Hash for PrivateKey { 177*971462beSGnoCiYeH fn hash<H: ~const Hasher>(&self, state: &mut H) { 178*971462beSGnoCiYeH self.address.hash(state); 179*971462beSGnoCiYeH } 180*971462beSGnoCiYeH } 181*971462beSGnoCiYeH 182*971462beSGnoCiYeH impl Eq for PrivateKey {} 183*971462beSGnoCiYeH 184*971462beSGnoCiYeH impl PartialEq for PrivateKey { 185*971462beSGnoCiYeH fn eq(&self, other: &Self) -> bool { 186*971462beSGnoCiYeH if self.address_space.is_none() && other.address_space.is_none() { 187*971462beSGnoCiYeH return self.address == other.address; 188*971462beSGnoCiYeH } else { 189*971462beSGnoCiYeH return self 190*971462beSGnoCiYeH .address_space 191*971462beSGnoCiYeH .as_ref() 192*971462beSGnoCiYeH .unwrap_or(&Weak::default()) 193*971462beSGnoCiYeH .ptr_eq(&other.address_space.as_ref().unwrap_or(&Weak::default())) 194*971462beSGnoCiYeH && self.address == other.address; 195*971462beSGnoCiYeH } 196*971462beSGnoCiYeH } 197*971462beSGnoCiYeH } 198*971462beSGnoCiYeH 199*971462beSGnoCiYeH impl Futex { 200*971462beSGnoCiYeH /// ### 初始化FUTEX_DATA 201*971462beSGnoCiYeH pub fn init() { 202*971462beSGnoCiYeH unsafe { 203*971462beSGnoCiYeH FUTEX_DATA = Some(FutexData { 204*971462beSGnoCiYeH data: SpinLock::new(HashMap::new()), 205*971462beSGnoCiYeH }) 206*971462beSGnoCiYeH }; 207*971462beSGnoCiYeH } 208*971462beSGnoCiYeH 209*971462beSGnoCiYeH /// ### 让当前进程在指定futex上等待直到futex_wake显式唤醒 210*971462beSGnoCiYeH pub fn futex_wait( 211*971462beSGnoCiYeH uaddr: VirtAddr, 212*971462beSGnoCiYeH flags: FutexFlag, 213*971462beSGnoCiYeH val: u32, 214*971462beSGnoCiYeH abs_time: Option<TimeSpec>, 215*971462beSGnoCiYeH bitset: u32, 216*971462beSGnoCiYeH ) -> Result<usize, SystemError> { 217*971462beSGnoCiYeH if bitset == 0 { 218*971462beSGnoCiYeH return Err(SystemError::EINVAL); 219*971462beSGnoCiYeH } 220*971462beSGnoCiYeH 221*971462beSGnoCiYeH // 获取全局hash表的key值 222*971462beSGnoCiYeH let key = Self::get_futex_key( 223*971462beSGnoCiYeH uaddr, 224*971462beSGnoCiYeH flags.contains(FutexFlag::FLAGS_SHARED), 225*971462beSGnoCiYeH FutexAccess::FutexRead, 226*971462beSGnoCiYeH )?; 227*971462beSGnoCiYeH 228*971462beSGnoCiYeH let mut futex_map_guard = FutexData::futex_map(); 229*971462beSGnoCiYeH let bucket = futex_map_guard.get_mut(&key); 230*971462beSGnoCiYeH let bucket_mut = match bucket { 231*971462beSGnoCiYeH Some(bucket) => bucket, 232*971462beSGnoCiYeH None => { 233*971462beSGnoCiYeH let bucket = FutexHashBucket { 234*971462beSGnoCiYeH chain: LinkedList::new(), 235*971462beSGnoCiYeH }; 236*971462beSGnoCiYeH futex_map_guard.insert(key.clone(), bucket); 237*971462beSGnoCiYeH futex_map_guard.get_mut(&key).unwrap() 238*971462beSGnoCiYeH } 239*971462beSGnoCiYeH }; 240*971462beSGnoCiYeH 241*971462beSGnoCiYeH // 使用UserBuffer读取futex 242*971462beSGnoCiYeH let user_reader = 243*971462beSGnoCiYeH UserBufferReader::new(uaddr.as_ptr::<u32>(), core::mem::size_of::<u32>(), true)?; 244*971462beSGnoCiYeH 245*971462beSGnoCiYeH // 从用户空间读取到futex的val 246*971462beSGnoCiYeH let mut uval = 0; 247*971462beSGnoCiYeH 248*971462beSGnoCiYeH // 读取 249*971462beSGnoCiYeH // 这里只尝试一种方式去读取用户空间,与linux不太一致 250*971462beSGnoCiYeH // 对于linux,如果bucket被锁住时读取失败,将会将bucket解锁后重新读取 251*971462beSGnoCiYeH user_reader.copy_one_from_user::<u32>(&mut uval, 0)?; 252*971462beSGnoCiYeH 253*971462beSGnoCiYeH // 不满足wait条件,返回错误 254*971462beSGnoCiYeH if uval != val { 255*971462beSGnoCiYeH return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 256*971462beSGnoCiYeH } 257*971462beSGnoCiYeH 258*971462beSGnoCiYeH let pcb = ProcessManager::current_pcb(); 259*971462beSGnoCiYeH // 创建超时计时器任务 260*971462beSGnoCiYeH let mut timer = None; 261*971462beSGnoCiYeH if !abs_time.is_none() { 262*971462beSGnoCiYeH let time = abs_time.unwrap(); 263*971462beSGnoCiYeH 264*971462beSGnoCiYeH let wakeup_helper = WakeUpHelper::new(pcb.clone()); 265*971462beSGnoCiYeH 266*971462beSGnoCiYeH let sec = time.tv_sec; 267*971462beSGnoCiYeH let nsec = time.tv_nsec; 268*971462beSGnoCiYeH let jiffies = next_n_us_timer_jiffies((nsec / 1000 + sec * 1_000_000) as u64); 269*971462beSGnoCiYeH 270*971462beSGnoCiYeH let wake_up = Timer::new(wakeup_helper, jiffies); 271*971462beSGnoCiYeH 272*971462beSGnoCiYeH wake_up.activate(); 273*971462beSGnoCiYeH timer = Some(wake_up); 274*971462beSGnoCiYeH } 275*971462beSGnoCiYeH 276*971462beSGnoCiYeH let futex_q = Arc::new(FutexObj { 277*971462beSGnoCiYeH pcb: Arc::downgrade(&pcb), 278*971462beSGnoCiYeH key: key.clone(), 279*971462beSGnoCiYeH bitset, 280*971462beSGnoCiYeH }); 281*971462beSGnoCiYeH let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 282*971462beSGnoCiYeH // 满足条件则将当前进程在该bucket上挂起 283*971462beSGnoCiYeH bucket_mut.sleep_no_sched(futex_q.clone()).map_err(|e| { 284*971462beSGnoCiYeH kwarn!("error:{e:?}"); 285*971462beSGnoCiYeH e 286*971462beSGnoCiYeH })?; 287*971462beSGnoCiYeH drop(bucket_mut); 288*971462beSGnoCiYeH drop(futex_map_guard); 289*971462beSGnoCiYeH drop(irq_guard); 290*971462beSGnoCiYeH sched(); 291*971462beSGnoCiYeH 292*971462beSGnoCiYeH // 被唤醒后的检查 293*971462beSGnoCiYeH let mut futex_map_guard = FutexData::futex_map(); 294*971462beSGnoCiYeH let bucket = futex_map_guard.get_mut(&key); 295*971462beSGnoCiYeH let bucket_mut = match bucket { 296*971462beSGnoCiYeH // 如果该pcb不在链表里面了或者该链表已经被释放,就证明是正常的Wake操作 297*971462beSGnoCiYeH Some(bucket_mut) => { 298*971462beSGnoCiYeH if !bucket_mut.contains(&futex_q) { 299*971462beSGnoCiYeH // 取消定时器任务 300*971462beSGnoCiYeH if timer.is_some() { 301*971462beSGnoCiYeH timer.unwrap().cancel(); 302*971462beSGnoCiYeH } 303*971462beSGnoCiYeH return Ok(0); 304*971462beSGnoCiYeH } 305*971462beSGnoCiYeH // 非正常唤醒,返回交给下层 306*971462beSGnoCiYeH bucket_mut 307*971462beSGnoCiYeH } 308*971462beSGnoCiYeH None => { 309*971462beSGnoCiYeH // 取消定时器任务 310*971462beSGnoCiYeH if timer.is_some() { 311*971462beSGnoCiYeH timer.unwrap().cancel(); 312*971462beSGnoCiYeH } 313*971462beSGnoCiYeH return Ok(0); 314*971462beSGnoCiYeH } 315*971462beSGnoCiYeH }; 316*971462beSGnoCiYeH 317*971462beSGnoCiYeH // 如果是超时唤醒,则返回错误 318*971462beSGnoCiYeH if timer.is_some() { 319*971462beSGnoCiYeH if timer.clone().unwrap().timeout() { 320*971462beSGnoCiYeH bucket_mut.remove(futex_q); 321*971462beSGnoCiYeH 322*971462beSGnoCiYeH return Err(SystemError::ETIMEDOUT); 323*971462beSGnoCiYeH } 324*971462beSGnoCiYeH } 325*971462beSGnoCiYeH 326*971462beSGnoCiYeH // TODO: 如果没有挂起的信号,则重新判断是否满足wait要求,重新进入wait 327*971462beSGnoCiYeH 328*971462beSGnoCiYeH // 经过前面的几个判断,到这里之后, 329*971462beSGnoCiYeH // 当前进程被唤醒大概率是其他进程更改了uval,需要重新去判断当前进程是否满足wait 330*971462beSGnoCiYeH 331*971462beSGnoCiYeH // 到这里之后,前面的唤醒条件都不满足,则是被信号唤醒 332*971462beSGnoCiYeH // 需要处理信号然后重启futex系统调用 333*971462beSGnoCiYeH 334*971462beSGnoCiYeH // 取消定时器任务 335*971462beSGnoCiYeH if timer.is_some() { 336*971462beSGnoCiYeH let timer = timer.unwrap(); 337*971462beSGnoCiYeH if !timer.timeout() { 338*971462beSGnoCiYeH timer.cancel(); 339*971462beSGnoCiYeH } 340*971462beSGnoCiYeH } 341*971462beSGnoCiYeH Ok(0) 342*971462beSGnoCiYeH } 343*971462beSGnoCiYeH 344*971462beSGnoCiYeH // ### 唤醒指定futex上挂起的最多nr_wake个进程 345*971462beSGnoCiYeH pub fn futex_wake( 346*971462beSGnoCiYeH uaddr: VirtAddr, 347*971462beSGnoCiYeH flags: FutexFlag, 348*971462beSGnoCiYeH nr_wake: u32, 349*971462beSGnoCiYeH bitset: u32, 350*971462beSGnoCiYeH ) -> Result<usize, SystemError> { 351*971462beSGnoCiYeH if bitset == 0 { 352*971462beSGnoCiYeH return Err(SystemError::EINVAL); 353*971462beSGnoCiYeH } 354*971462beSGnoCiYeH 355*971462beSGnoCiYeH // 获取futex_key,并且判断地址空间合法性 356*971462beSGnoCiYeH let key = Self::get_futex_key( 357*971462beSGnoCiYeH uaddr, 358*971462beSGnoCiYeH flags.contains(FutexFlag::FLAGS_SHARED), 359*971462beSGnoCiYeH FutexAccess::FutexRead, 360*971462beSGnoCiYeH )?; 361*971462beSGnoCiYeH let mut binding = FutexData::futex_map(); 362*971462beSGnoCiYeH let bucket_mut = binding.get_mut(&key).ok_or(SystemError::EINVAL)?; 363*971462beSGnoCiYeH 364*971462beSGnoCiYeH // 确保后面的唤醒操作是有意义的 365*971462beSGnoCiYeH if bucket_mut.chain.is_empty() { 366*971462beSGnoCiYeH return Ok(0); 367*971462beSGnoCiYeH } 368*971462beSGnoCiYeH // 从队列中唤醒 369*971462beSGnoCiYeH let count = bucket_mut.wake_up(key.clone(), Some(bitset), nr_wake)?; 370*971462beSGnoCiYeH 371*971462beSGnoCiYeH drop(bucket_mut); 372*971462beSGnoCiYeH drop(binding); 373*971462beSGnoCiYeH 374*971462beSGnoCiYeH FutexData::try_remove(&key); 375*971462beSGnoCiYeH 376*971462beSGnoCiYeH Ok(count) 377*971462beSGnoCiYeH } 378*971462beSGnoCiYeH 379*971462beSGnoCiYeH /// ### 唤醒制定uaddr1上的最多nr_wake个进程,然后将uaddr1最多nr_requeue个进程移动到uaddr2绑定的futex上 380*971462beSGnoCiYeH pub fn futex_requeue( 381*971462beSGnoCiYeH uaddr1: VirtAddr, 382*971462beSGnoCiYeH flags: FutexFlag, 383*971462beSGnoCiYeH uaddr2: VirtAddr, 384*971462beSGnoCiYeH nr_wake: i32, 385*971462beSGnoCiYeH nr_requeue: i32, 386*971462beSGnoCiYeH cmpval: Option<u32>, 387*971462beSGnoCiYeH requeue_pi: bool, 388*971462beSGnoCiYeH ) -> Result<usize, SystemError> { 389*971462beSGnoCiYeH if nr_requeue < 0 || nr_wake < 0 { 390*971462beSGnoCiYeH return Err(SystemError::EINVAL); 391*971462beSGnoCiYeH } 392*971462beSGnoCiYeH 393*971462beSGnoCiYeH // 暂时不支持优先级继承 394*971462beSGnoCiYeH if requeue_pi { 395*971462beSGnoCiYeH return Err(SystemError::ENOSYS); 396*971462beSGnoCiYeH } 397*971462beSGnoCiYeH 398*971462beSGnoCiYeH let key1 = Self::get_futex_key( 399*971462beSGnoCiYeH uaddr1, 400*971462beSGnoCiYeH flags.contains(FutexFlag::FLAGS_SHARED), 401*971462beSGnoCiYeH FutexAccess::FutexRead, 402*971462beSGnoCiYeH )?; 403*971462beSGnoCiYeH let key2 = Self::get_futex_key(uaddr2, flags.contains(FutexFlag::FLAGS_SHARED), { 404*971462beSGnoCiYeH match requeue_pi { 405*971462beSGnoCiYeH true => FutexAccess::FutexWrite, 406*971462beSGnoCiYeH false => FutexAccess::FutexRead, 407*971462beSGnoCiYeH } 408*971462beSGnoCiYeH })?; 409*971462beSGnoCiYeH 410*971462beSGnoCiYeH if requeue_pi && key1 == key2 { 411*971462beSGnoCiYeH return Err(SystemError::EINVAL); 412*971462beSGnoCiYeH } 413*971462beSGnoCiYeH 414*971462beSGnoCiYeH if likely(!cmpval.is_none()) { 415*971462beSGnoCiYeH let uval_reader = 416*971462beSGnoCiYeH UserBufferReader::new(uaddr1.as_ptr::<u32>(), core::mem::size_of::<u32>(), true)?; 417*971462beSGnoCiYeH let curval = uval_reader.read_one_from_user::<u32>(0)?; 418*971462beSGnoCiYeH 419*971462beSGnoCiYeH // 判断是否满足条件 420*971462beSGnoCiYeH if *curval != cmpval.unwrap() { 421*971462beSGnoCiYeH return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 422*971462beSGnoCiYeH } 423*971462beSGnoCiYeH } 424*971462beSGnoCiYeH 425*971462beSGnoCiYeH let mut futex_data_guard = FutexData::futex_map(); 426*971462beSGnoCiYeH if !requeue_pi { 427*971462beSGnoCiYeH // 唤醒nr_wake个进程 428*971462beSGnoCiYeH let bucket_1_mut = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?; 429*971462beSGnoCiYeH let ret = bucket_1_mut.wake_up(key1.clone(), None, nr_wake as u32)?; 430*971462beSGnoCiYeH drop(bucket_1_mut); 431*971462beSGnoCiYeH // 将bucket1中最多nr_requeue个任务转移到bucket2 432*971462beSGnoCiYeH for _ in 0..nr_requeue { 433*971462beSGnoCiYeH let bucket_1_mut = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?; 434*971462beSGnoCiYeH let futex_q = bucket_1_mut.chain.pop_front(); 435*971462beSGnoCiYeH match futex_q { 436*971462beSGnoCiYeH Some(futex_q) => { 437*971462beSGnoCiYeH let bucket_2_mut = 438*971462beSGnoCiYeH futex_data_guard.get_mut(&key2).ok_or(SystemError::EINVAL)?; 439*971462beSGnoCiYeH bucket_2_mut.chain.push_back(futex_q); 440*971462beSGnoCiYeH } 441*971462beSGnoCiYeH None => { 442*971462beSGnoCiYeH break; 443*971462beSGnoCiYeH } 444*971462beSGnoCiYeH } 445*971462beSGnoCiYeH } 446*971462beSGnoCiYeH 447*971462beSGnoCiYeH return Ok(ret); 448*971462beSGnoCiYeH } else { 449*971462beSGnoCiYeH // 暂时不支持优先级继承 450*971462beSGnoCiYeH todo!() 451*971462beSGnoCiYeH } 452*971462beSGnoCiYeH } 453*971462beSGnoCiYeH 454*971462beSGnoCiYeH /// ### 唤醒futex上的进程的同时进行一些操作 455*971462beSGnoCiYeH pub fn futex_wake_op( 456*971462beSGnoCiYeH uaddr1: VirtAddr, 457*971462beSGnoCiYeH flags: FutexFlag, 458*971462beSGnoCiYeH uaddr2: VirtAddr, 459*971462beSGnoCiYeH nr_wake: i32, 460*971462beSGnoCiYeH nr_wake2: i32, 461*971462beSGnoCiYeH op: i32, 462*971462beSGnoCiYeH ) -> Result<usize, SystemError> { 463*971462beSGnoCiYeH let key1 = Futex::get_futex_key( 464*971462beSGnoCiYeH uaddr1, 465*971462beSGnoCiYeH flags.contains(FutexFlag::FLAGS_SHARED), 466*971462beSGnoCiYeH FutexAccess::FutexRead, 467*971462beSGnoCiYeH )?; 468*971462beSGnoCiYeH let key2 = Futex::get_futex_key( 469*971462beSGnoCiYeH uaddr2, 470*971462beSGnoCiYeH flags.contains(FutexFlag::FLAGS_SHARED), 471*971462beSGnoCiYeH FutexAccess::FutexWrite, 472*971462beSGnoCiYeH )?; 473*971462beSGnoCiYeH 474*971462beSGnoCiYeH let mut futex_data_guard = FutexData::futex_map(); 475*971462beSGnoCiYeH let bucket1 = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?; 476*971462beSGnoCiYeH let mut wake_count = 0; 477*971462beSGnoCiYeH 478*971462beSGnoCiYeH // 唤醒uaddr1中的进程 479*971462beSGnoCiYeH wake_count += bucket1.wake_up(key1, None, nr_wake as u32)?; 480*971462beSGnoCiYeH 481*971462beSGnoCiYeH match Self::futex_atomic_op_inuser(op as u32, uaddr2) { 482*971462beSGnoCiYeH Ok(ret) => { 483*971462beSGnoCiYeH // 操作成功则唤醒uaddr2中的进程 484*971462beSGnoCiYeH if ret { 485*971462beSGnoCiYeH let bucket2 = futex_data_guard.get_mut(&key2).ok_or(SystemError::EINVAL)?; 486*971462beSGnoCiYeH wake_count += bucket2.wake_up(key2, None, nr_wake2 as u32)?; 487*971462beSGnoCiYeH } 488*971462beSGnoCiYeH } 489*971462beSGnoCiYeH Err(e) => { 490*971462beSGnoCiYeH // TODO:retry? 491*971462beSGnoCiYeH return Err(e); 492*971462beSGnoCiYeH } 493*971462beSGnoCiYeH } 494*971462beSGnoCiYeH 495*971462beSGnoCiYeH Ok(wake_count) 496*971462beSGnoCiYeH } 497*971462beSGnoCiYeH 498*971462beSGnoCiYeH fn get_futex_key( 499*971462beSGnoCiYeH uaddr: VirtAddr, 500*971462beSGnoCiYeH fshared: bool, 501*971462beSGnoCiYeH _access: FutexAccess, 502*971462beSGnoCiYeH ) -> Result<FutexKey, SystemError> { 503*971462beSGnoCiYeH let mut address = uaddr.data(); 504*971462beSGnoCiYeH 505*971462beSGnoCiYeH // 计算相对页的偏移量 506*971462beSGnoCiYeH let offset = address & (MMArch::PAGE_SIZE - 1); 507*971462beSGnoCiYeH // 判断内存对齐 508*971462beSGnoCiYeH if !(uaddr.data() & (core::mem::size_of::<u32>() - 1) == 0) { 509*971462beSGnoCiYeH return Err(SystemError::EINVAL); 510*971462beSGnoCiYeH } 511*971462beSGnoCiYeH 512*971462beSGnoCiYeH // 目前address指向所在页面的起始地址 513*971462beSGnoCiYeH address -= offset; 514*971462beSGnoCiYeH 515*971462beSGnoCiYeH // 若不是进程间共享的futex,则返回Private 516*971462beSGnoCiYeH if !fshared { 517*971462beSGnoCiYeH return Ok(FutexKey { 518*971462beSGnoCiYeH ptr: 0, 519*971462beSGnoCiYeH word: 0, 520*971462beSGnoCiYeH offset: offset as u32, 521*971462beSGnoCiYeH key: InnerFutexKey::Private(PrivateKey { 522*971462beSGnoCiYeH address: address as u64, 523*971462beSGnoCiYeH address_space: None, 524*971462beSGnoCiYeH }), 525*971462beSGnoCiYeH }); 526*971462beSGnoCiYeH } 527*971462beSGnoCiYeH 528*971462beSGnoCiYeH // 获取到地址所在地址空间 529*971462beSGnoCiYeH let address_space = AddressSpace::current()?; 530*971462beSGnoCiYeH // TODO: 判断是否为匿名映射,是匿名映射才返回PrivateKey 531*971462beSGnoCiYeH return Ok(FutexKey { 532*971462beSGnoCiYeH ptr: 0, 533*971462beSGnoCiYeH word: 0, 534*971462beSGnoCiYeH offset: offset as u32, 535*971462beSGnoCiYeH key: InnerFutexKey::Private(PrivateKey { 536*971462beSGnoCiYeH address: address as u64, 537*971462beSGnoCiYeH address_space: Some(Arc::downgrade(&address_space)), 538*971462beSGnoCiYeH }), 539*971462beSGnoCiYeH }); 540*971462beSGnoCiYeH 541*971462beSGnoCiYeH // 未实现共享内存机制,贡献内存部分应该通过inode构建SharedKey 542*971462beSGnoCiYeH // todo!("Shared memory not implemented"); 543*971462beSGnoCiYeH } 544*971462beSGnoCiYeH 545*971462beSGnoCiYeH pub fn futex_atomic_op_inuser(encoded_op: u32, uaddr: VirtAddr) -> Result<bool, SystemError> { 546*971462beSGnoCiYeH let op = FutexOP::from_bits((encoded_op & 0x70000000) >> 28).ok_or(SystemError::ENOSYS)?; 547*971462beSGnoCiYeH let cmp = 548*971462beSGnoCiYeH FutexOpCMP::from_bits((encoded_op & 0x0f000000) >> 24).ok_or(SystemError::ENOSYS)?; 549*971462beSGnoCiYeH 550*971462beSGnoCiYeH let sign_extend32 = |value: u32, index: i32| { 551*971462beSGnoCiYeH let shift = (31 - index) as u8; 552*971462beSGnoCiYeH return (value << shift) >> shift; 553*971462beSGnoCiYeH }; 554*971462beSGnoCiYeH 555*971462beSGnoCiYeH let mut oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 11); 556*971462beSGnoCiYeH let cmparg = sign_extend32(encoded_op & 0x00000fff, 11); 557*971462beSGnoCiYeH 558*971462beSGnoCiYeH if encoded_op & (FutexOP::FUTEX_OP_OPARG_SHIFT.bits() << 28) != 0 { 559*971462beSGnoCiYeH if oparg > 31 { 560*971462beSGnoCiYeH kwarn!( 561*971462beSGnoCiYeH "futex_wake_op: pid:{} tries to shift op by {}; fix this program", 562*971462beSGnoCiYeH ProcessManager::current_pcb().pid().data(), 563*971462beSGnoCiYeH oparg 564*971462beSGnoCiYeH ); 565*971462beSGnoCiYeH 566*971462beSGnoCiYeH oparg &= 31; 567*971462beSGnoCiYeH } 568*971462beSGnoCiYeH } 569*971462beSGnoCiYeH 570*971462beSGnoCiYeH // TODO: 这个汇编似乎是有问题的,目前不好测试 571*971462beSGnoCiYeH let old_val = Self::arch_futex_atomic_op_inuser(op, oparg, uaddr)?; 572*971462beSGnoCiYeH 573*971462beSGnoCiYeH match cmp { 574*971462beSGnoCiYeH FutexOpCMP::FUTEX_OP_CMP_EQ => { 575*971462beSGnoCiYeH return Ok(cmparg == old_val); 576*971462beSGnoCiYeH } 577*971462beSGnoCiYeH FutexOpCMP::FUTEX_OP_CMP_NE => { 578*971462beSGnoCiYeH return Ok(cmparg != old_val); 579*971462beSGnoCiYeH } 580*971462beSGnoCiYeH FutexOpCMP::FUTEX_OP_CMP_LT => { 581*971462beSGnoCiYeH return Ok(cmparg < old_val); 582*971462beSGnoCiYeH } 583*971462beSGnoCiYeH FutexOpCMP::FUTEX_OP_CMP_LE => { 584*971462beSGnoCiYeH return Ok(cmparg <= old_val); 585*971462beSGnoCiYeH } 586*971462beSGnoCiYeH FutexOpCMP::FUTEX_OP_CMP_GE => { 587*971462beSGnoCiYeH return Ok(cmparg >= old_val); 588*971462beSGnoCiYeH } 589*971462beSGnoCiYeH FutexOpCMP::FUTEX_OP_CMP_GT => { 590*971462beSGnoCiYeH return Ok(cmparg > old_val); 591*971462beSGnoCiYeH } 592*971462beSGnoCiYeH _ => { 593*971462beSGnoCiYeH return Err(SystemError::ENOSYS); 594*971462beSGnoCiYeH } 595*971462beSGnoCiYeH } 596*971462beSGnoCiYeH } 597*971462beSGnoCiYeH 598*971462beSGnoCiYeH /// ### 对futex进行操作 599*971462beSGnoCiYeH /// 600*971462beSGnoCiYeH /// 进入该方法会关闭中断保证修改的原子性,所以进入该方法前应确保中断锁已释放 601*971462beSGnoCiYeH /// 602*971462beSGnoCiYeH /// ### return uaddr原来的值 603*971462beSGnoCiYeH #[allow(unused_assignments)] 604*971462beSGnoCiYeH pub fn arch_futex_atomic_op_inuser( 605*971462beSGnoCiYeH op: FutexOP, 606*971462beSGnoCiYeH oparg: u32, 607*971462beSGnoCiYeH uaddr: VirtAddr, 608*971462beSGnoCiYeH ) -> Result<u32, SystemError> { 609*971462beSGnoCiYeH let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 610*971462beSGnoCiYeH 611*971462beSGnoCiYeH let reader = 612*971462beSGnoCiYeH UserBufferReader::new(uaddr.as_ptr::<u32>(), core::mem::size_of::<u32>(), true)?; 613*971462beSGnoCiYeH 614*971462beSGnoCiYeH let oldval = reader.read_one_from_user::<u32>(0)?; 615*971462beSGnoCiYeH 616*971462beSGnoCiYeH let atomic_addr = AtomicU64::new(uaddr.data() as u64); 617*971462beSGnoCiYeH // 这个指针是指向指针的指针 618*971462beSGnoCiYeH let ptr = atomic_addr.as_mut_ptr(); 619*971462beSGnoCiYeH match op { 620*971462beSGnoCiYeH FutexOP::FUTEX_OP_SET => unsafe { 621*971462beSGnoCiYeH *((*ptr) as *mut u32) = oparg; 622*971462beSGnoCiYeH }, 623*971462beSGnoCiYeH FutexOP::FUTEX_OP_ADD => unsafe { 624*971462beSGnoCiYeH *((*ptr) as *mut u32) += oparg; 625*971462beSGnoCiYeH }, 626*971462beSGnoCiYeH FutexOP::FUTEX_OP_OR => unsafe { 627*971462beSGnoCiYeH *((*ptr) as *mut u32) |= oparg; 628*971462beSGnoCiYeH }, 629*971462beSGnoCiYeH FutexOP::FUTEX_OP_ANDN => unsafe { 630*971462beSGnoCiYeH *((*ptr) as *mut u32) &= oparg; 631*971462beSGnoCiYeH }, 632*971462beSGnoCiYeH FutexOP::FUTEX_OP_XOR => unsafe { 633*971462beSGnoCiYeH *((*ptr) as *mut u32) ^= oparg; 634*971462beSGnoCiYeH }, 635*971462beSGnoCiYeH _ => return Err(SystemError::ENOSYS), 636*971462beSGnoCiYeH } 637*971462beSGnoCiYeH 638*971462beSGnoCiYeH drop(guard); 639*971462beSGnoCiYeH 640*971462beSGnoCiYeH Ok(*oldval) 641*971462beSGnoCiYeH } 642*971462beSGnoCiYeH } 643*971462beSGnoCiYeH 644*971462beSGnoCiYeH #[no_mangle] 645*971462beSGnoCiYeH unsafe extern "C" fn rs_futex_init() { 646*971462beSGnoCiYeH Futex::init(); 647*971462beSGnoCiYeH } 648