xref: /DragonOS/kernel/src/libs/futex/futex.rs (revision 971462be94ba0a5c74af7a5f9653dfabd4932a63)
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