Use WaitQueue to implement waiting in FutexWaiter

This commit is contained in:
Yuke Peng
2024-07-18 19:52:42 +08:00
committed by Tate, Hongliang Tian
parent 34f6108f56
commit 31746e2ebf

View File

@ -4,14 +4,10 @@
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use ostd::cpu::num_cpus; use ostd::{cpu::num_cpus, sync::WaitQueue};
use spin::Once; use spin::Once;
use crate::{ use crate::{prelude::*, thread::Tid, util::read_val_from_user};
prelude::*,
thread::{Thread, Tid},
util::read_val_from_user,
};
type FutexBitSet = u32; type FutexBitSet = u32;
type FutexBucketRef = Arc<Mutex<FutexBucket>>; type FutexBucketRef = Arc<Mutex<FutexBucket>>;
@ -51,7 +47,7 @@ pub fn futex_wait_bitset(
// drop lock // drop lock
drop(futex_bucket); drop(futex_bucket);
// Wait on the futex item // Wait on the futex item
futex_item.wait(); futex_item.wait(timeout.clone());
Ok(()) Ok(())
} }
@ -302,9 +298,9 @@ impl FutexItem {
self.waiter.wake(); self.waiter.wake();
} }
pub fn wait(&self) { pub fn wait(&self, timeout: Option<FutexTimeout>) {
// debug!("wait on futex item, key = {:?}", self.key); // debug!("wait on futex item, key = {:?}", self.key);
self.waiter.wait(); self.waiter.wait(timeout);
// debug!("wait finished, key = {:?}", self.key); // debug!("wait finished, key = {:?}", self.key);
} }
@ -403,12 +399,21 @@ pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags)> {
type FutexWaiterRef = Arc<FutexWaiter>; type FutexWaiterRef = Arc<FutexWaiter>;
#[derive(Debug)]
struct FutexWaiter { struct FutexWaiter {
is_woken: AtomicBool, is_woken: AtomicBool,
wait_queue: WaitQueue,
tid: Tid, tid: Tid,
} }
impl Debug for FutexWaiter {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("FutexWaiter")
.field("is_woken", &self.is_woken)
.field("tid", &self.tid)
.finish()
}
}
impl PartialEq for FutexWaiter { impl PartialEq for FutexWaiter {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.tid == other.tid self.tid == other.tid
@ -420,26 +425,37 @@ impl FutexWaiter {
Self { Self {
is_woken: AtomicBool::new(false), is_woken: AtomicBool::new(false),
tid: current_thread!().tid(), tid: current_thread!().tid(),
wait_queue: WaitQueue::new(),
} }
} }
pub fn wait(&self) { pub fn wait(&self, timeout: Option<FutexTimeout>) {
let current_thread = current_thread!(); let current_thread = current_thread!();
if current_thread.tid() != self.tid { if current_thread.tid() != self.tid {
return; return;
} }
self.is_woken.store(false, Ordering::SeqCst); self.is_woken.store(false, Ordering::SeqCst);
while !self.is_woken() { let wake_cond = || {
// debug!("futex is wait for waken, tid = {}", self.tid); if self.is_woken() {
Thread::yield_now(); Some(())
} else {
None
}
};
if let Some(_timeout) = timeout {
todo!()
} else {
self.wait_queue.wait_until(wake_cond);
} }
// debug!("futex is waken, tid = {}", self.tid);
} }
pub fn wake(&self) { pub fn wake(&self) {
if !self.is_woken() { if !self.is_woken() {
// debug!("wake up futex, tid = {}", self.tid); // debug!("wake up futex, tid = {}", self.tid);
self.is_woken.store(true, Ordering::SeqCst); self.is_woken.store(true, Ordering::SeqCst);
self.wait_queue.wake_all();
} }
} }