mirror of
https://github.com/rcore-os/rCore.git
synced 2025-01-31 10:04:04 +04:00
Implement futex timeout
This commit is contained in:
parent
f0c418e969
commit
fbc8757c22
@ -111,6 +111,7 @@ impl INode for TtyINode {
|
||||
fn async_poll<'a>(
|
||||
&'a self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<PollStatus>> + Send + Sync + 'a>> {
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct SerialFuture<'a> {
|
||||
tty: &'a TtyINode,
|
||||
};
|
||||
|
@ -133,6 +133,7 @@ impl INode for Pipe {
|
||||
fn async_poll<'a>(
|
||||
&'a self,
|
||||
) -> Pin<Box<dyn Future<Output = Result<PollStatus>> + Send + Sync + 'a>> {
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct PipeFuture<'a> {
|
||||
pipe: &'a Pipe,
|
||||
};
|
||||
|
@ -1,8 +1,14 @@
|
||||
use crate::{sync::SpinNoIrqLock as Mutex, syscall::SysResult};
|
||||
use crate::trap::NAIVE_TIMER;
|
||||
use crate::{
|
||||
arch::timer::timer_now,
|
||||
sync::SpinNoIrqLock as Mutex,
|
||||
syscall::{SysError, SysResult},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::{collections::VecDeque, sync::Arc};
|
||||
use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
use core::{future::Future, task::Waker};
|
||||
use core::{future::Future, task::Waker, time::Duration};
|
||||
|
||||
pub struct Waiter {
|
||||
waker: Option<Waker>,
|
||||
@ -43,10 +49,13 @@ impl Futex {
|
||||
wake_count
|
||||
}
|
||||
|
||||
pub fn wait(self: &Arc<Self>) -> impl Future<Output = SysResult> {
|
||||
pub fn wait(self: &Arc<Self>, timeout: Option<Duration>) -> impl Future<Output = SysResult> {
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct FutexFuture {
|
||||
waiter: Arc<Mutex<Waiter>>,
|
||||
deadline: Option<Duration>,
|
||||
}
|
||||
|
||||
impl Future for FutexFuture {
|
||||
type Output = SysResult;
|
||||
|
||||
@ -56,12 +65,28 @@ impl Futex {
|
||||
if inner.woken {
|
||||
return Poll::Ready(Ok(0));
|
||||
}
|
||||
if let Some(deadline) = self.deadline {
|
||||
if timer_now() >= deadline {
|
||||
inner.woken = true;
|
||||
return Poll::Ready(Err(SysError::ETIMEDOUT));
|
||||
}
|
||||
}
|
||||
|
||||
// first time?
|
||||
if inner.waker.is_none() {
|
||||
// futex
|
||||
let mut futex = inner.futex.inner.lock();
|
||||
futex.waiters.push_back(self.waiter.clone());
|
||||
drop(futex);
|
||||
inner.waker.replace(cx.waker().clone());
|
||||
|
||||
// timer
|
||||
if let Some(deadline) = self.deadline {
|
||||
let waker = cx.waker().clone();
|
||||
NAIVE_TIMER
|
||||
.lock()
|
||||
.add(deadline, Box::new(move |_| waker.wake()));
|
||||
}
|
||||
}
|
||||
Poll::Pending
|
||||
}
|
||||
@ -73,6 +98,7 @@ impl Futex {
|
||||
woken: false,
|
||||
futex: self.clone(),
|
||||
})),
|
||||
deadline: timeout.map(|t| timer_now() + t),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -477,6 +477,7 @@ fn spawn_thread(
|
||||
});
|
||||
}
|
||||
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct PageTableSwitchWrapper {
|
||||
inner: Mutex<Pin<Box<dyn Future<Output = ()> + Send>>>,
|
||||
vmtoken: usize,
|
||||
|
@ -64,6 +64,7 @@ pub fn wait_for_event(bus: Arc<Mutex<EventBus>>, mask: Event) -> impl Future<Out
|
||||
EventBusFuture { bus, mask }
|
||||
}
|
||||
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct EventBusFuture {
|
||||
bus: Arc<Mutex<EventBus>>,
|
||||
mask: Event,
|
||||
|
@ -140,6 +140,7 @@ impl Syscall<'_> {
|
||||
|
||||
drop(proc);
|
||||
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
struct PollFuture<'a> {
|
||||
polls: Vec<PollFd>,
|
||||
syscall: &'a Syscall<'a>,
|
||||
|
@ -95,13 +95,13 @@ impl Syscall<'_> {
|
||||
// avoid deadlock
|
||||
drop(proc);
|
||||
if timeout.is_null() {
|
||||
queue.wait().await?;
|
||||
queue.wait(None).await?;
|
||||
Ok(0)
|
||||
} else {
|
||||
// TODO: timeout
|
||||
let timeout = timeout.read()?;
|
||||
info!("futex wait timeout: {:?}", timeout);
|
||||
queue.wait().await?;
|
||||
queue.wait(Some(timeout.to_duration())).await?;
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
@ -401,14 +401,17 @@ impl Syscall<'_> {
|
||||
}
|
||||
|
||||
// sleeping
|
||||
pub fn sleep_for(deadline: Duration) -> impl Future {
|
||||
pub fn sleep_for(duration: Duration) -> impl Future {
|
||||
SleepFuture {
|
||||
deadline: timer_now() + deadline,
|
||||
deadline: timer_now() + duration,
|
||||
duration,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "future does nothing unless polled/`await`-ed"]
|
||||
pub struct SleepFuture {
|
||||
deadline: Duration,
|
||||
duration: Duration,
|
||||
}
|
||||
|
||||
impl Future for SleepFuture {
|
||||
@ -419,7 +422,7 @@ impl Future for SleepFuture {
|
||||
return Poll::Ready(());
|
||||
}
|
||||
// check infinity
|
||||
if self.deadline.as_nanos() < i64::max_value() as u128 {
|
||||
if self.duration.as_nanos() < i64::max_value() as u128 {
|
||||
let waker = cx.waker().clone();
|
||||
NAIVE_TIMER
|
||||
.lock()
|
||||
|
Loading…
x
Reference in New Issue
Block a user