1
0
Fork 0
forked from wry/wry

it: wait for async engine and cpu worker to become idle

This commit is contained in:
Julian Orth 2024-09-28 22:26:01 +02:00
parent 58f82d889b
commit a9aad0c613
5 changed files with 59 additions and 3 deletions

View file

@ -35,6 +35,8 @@ pub struct AsyncEngine {
yield_stash: RefCell<VecDeque<Waker>>,
stopped: Cell<bool>,
now: Cell<Option<Time>>,
#[cfg(feature = "it")]
idle: Cell<Option<Waker>>,
}
impl AsyncEngine {
@ -48,6 +50,8 @@ impl AsyncEngine {
yield_stash: Default::default(),
stopped: Cell::new(false),
now: Default::default(),
#[cfg(feature = "it")]
idle: Default::default(),
})
}
@ -91,7 +95,15 @@ impl AsyncEngine {
pub fn dispatch(&self) {
let mut stash = self.stash.borrow_mut();
let mut yield_stash = self.yield_stash.borrow_mut();
while self.num_queued.get() > 0 {
loop {
if self.num_queued.get() == 0 {
#[cfg(feature = "it")]
if let Some(idle) = self.idle.take() {
idle.wake();
continue;
}
break;
}
self.now.take();
self.iteration.fetch_add(1);
let mut phase = 0;
@ -116,6 +128,22 @@ impl AsyncEngine {
}
}
#[cfg(feature = "it")]
pub async fn idle(&self) {
use std::{future::poll_fn, task::Poll};
let mut register = true;
poll_fn(|ctx| {
if register {
self.idle.set(Some(ctx.waker().clone()));
register = false;
Poll::Pending
} else {
Poll::Ready(())
}
})
.await
}
fn push(&self, runnable: Runnable, phase: Phase) {
self.queues[phase as usize].push(runnable);
self.num_queued.fetch_add(1);

View file

@ -321,6 +321,23 @@ impl CpuWorker {
job_data,
}
}
#[cfg(feature = "it")]
pub fn wait_idle(&self) -> bool {
let was_idle = self.data.pending_jobs.is_empty();
loop {
self.data.dispatch_completions();
if self.data.pending_jobs.is_empty() {
break;
}
let mut remote = self.data.completed_jobs_remote.lock();
while remote.queue.is_empty() {
remote.condvar = Some(self.data.sync_wake_condvar.clone());
self.data.sync_wake_condvar.wait(&mut remote);
}
}
was_idle
}
}
fn work(

View file

@ -85,10 +85,9 @@ impl TestClient {
}
pub async fn sync(&self) {
self.run.state.eng.yield_now().await;
self.run.sync().await;
self.tran.sync().await;
self.run.state.eng.yield_now().await;
self.run.state.idle().await;
}
pub async fn take_screenshot(&self, include_cursor: bool) -> Result<Vec<u8>, TestError> {

View file

@ -54,6 +54,8 @@ impl TestJayCompositor {
&self,
include_cursor: bool,
) -> Result<(DmaBuf, Option<Rc<OwnedFd>>), TestError> {
self.tran.sync().await;
self.tran.run.state.idle().await;
let js = Rc::new(TestJayScreenshot {
id: self.tran.id(),
state: self.tran.run.state.clone(),

View file

@ -1218,6 +1218,16 @@ impl State {
output.vblank();
}
}
#[cfg(feature = "it")]
pub async fn idle(&self) {
loop {
self.eng.idle().await;
if self.cpu_worker.wait_idle() {
break;
}
}
}
}
#[derive(Debug, Error)]