1
0
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:
Jiajie Chen 2020-06-20 07:55:20 +08:00
parent f0c418e969
commit fbc8757c22
8 changed files with 42 additions and 8 deletions

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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),
}
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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>,

View File

@ -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)
}
}

View File

@ -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()