metal: delay rendering until shortly before page flip
This commit is contained in:
parent
33d5c61c37
commit
c2d31cb639
9 changed files with 113 additions and 22 deletions
|
|
@ -51,7 +51,7 @@ impl IoUring {
|
|||
});
|
||||
self.ring.schedule(pw);
|
||||
if let Some(time) = timeout {
|
||||
self.schedule_timeout(time);
|
||||
self.schedule_timeout_link(time);
|
||||
}
|
||||
}
|
||||
Ok(pr.await.map(|v| v as usize)).merge()
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ impl IoUring {
|
|||
st.has_timeout = timeout.is_some();
|
||||
self.ring.schedule(st);
|
||||
if let Some(timeout) = timeout {
|
||||
self.schedule_timeout(timeout);
|
||||
self.schedule_timeout_link(timeout);
|
||||
}
|
||||
}
|
||||
Ok(pr.await? as _)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
use {
|
||||
crate::{
|
||||
io_uring::{
|
||||
sys::{io_uring_sqe, IORING_OP_LINK_TIMEOUT, IORING_TIMEOUT_ABS},
|
||||
IoUring, IoUringData, Task,
|
||||
},
|
||||
time::Time,
|
||||
crate::io_uring::{
|
||||
pending_result::PendingResult,
|
||||
sys::{io_uring_sqe, IORING_OP_TIMEOUT, IORING_TIMEOUT_ABS},
|
||||
IoUring, IoUringData, IoUringError, Task,
|
||||
},
|
||||
uapi::c,
|
||||
};
|
||||
|
|
@ -12,27 +10,35 @@ use {
|
|||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
struct timespec64 {
|
||||
tv_sec: i64,
|
||||
tv_nsec: c::c_long,
|
||||
pub(super) struct timespec64 {
|
||||
pub tv_sec: i64,
|
||||
pub tv_nsec: c::c_long,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TimeoutTask {
|
||||
id: u64,
|
||||
timespec: timespec64,
|
||||
pr: Option<PendingResult>,
|
||||
}
|
||||
|
||||
impl IoUring {
|
||||
pub(super) fn schedule_timeout(&self, timeout: Time) {
|
||||
let id = self.ring.id_raw();
|
||||
pub async fn timeout(&self, timeout_nsec: u64) -> Result<(), IoUringError> {
|
||||
self.ring.check_destroyed()?;
|
||||
let id = self.ring.id();
|
||||
let pr = self.ring.pending_results.acquire();
|
||||
{
|
||||
let mut to = self.ring.cached_timeouts.pop().unwrap_or_default();
|
||||
to.id = id;
|
||||
to.timespec.tv_sec = timeout.0.tv_sec as _;
|
||||
to.timespec.tv_nsec = timeout.0.tv_nsec as _;
|
||||
self.ring.schedule(to);
|
||||
let mut pw = self.ring.cached_timeouts.pop().unwrap_or_default();
|
||||
pw.id = id.id;
|
||||
pw.timespec = timespec64 {
|
||||
tv_sec: (timeout_nsec / 1_000_000_000) as _,
|
||||
tv_nsec: (timeout_nsec % 1_000_000_000) as _,
|
||||
};
|
||||
pw.pr = Some(pr.clone());
|
||||
self.ring.schedule(pw);
|
||||
}
|
||||
let _ = pr.await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +47,18 @@ unsafe impl Task for TimeoutTask {
|
|||
self.id
|
||||
}
|
||||
|
||||
fn complete(self: Box<Self>, ring: &IoUringData, _res: i32) {
|
||||
fn complete(mut self: Box<Self>, ring: &IoUringData, res: i32) {
|
||||
if let Some(pr) = self.pr.take() {
|
||||
pr.complete(res);
|
||||
}
|
||||
ring.cached_timeouts.push(self);
|
||||
}
|
||||
|
||||
fn encode(&self, sqe: &mut io_uring_sqe) {
|
||||
sqe.opcode = IORING_OP_LINK_TIMEOUT;
|
||||
sqe.opcode = IORING_OP_TIMEOUT;
|
||||
sqe.u2.addr = &self.timespec as *const _ as _;
|
||||
sqe.len = 1;
|
||||
sqe.u3.timeout_flags = IORING_TIMEOUT_ABS;
|
||||
sqe.u1.off = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
44
src/io_uring/ops/timeout_link.rs
Normal file
44
src/io_uring/ops/timeout_link.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use crate::{
|
||||
io_uring::{
|
||||
ops::timeout::timespec64,
|
||||
sys::{io_uring_sqe, IORING_OP_LINK_TIMEOUT, IORING_TIMEOUT_ABS},
|
||||
IoUring, IoUringData, Task,
|
||||
},
|
||||
time::Time,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TimeoutLinkTask {
|
||||
id: u64,
|
||||
timespec: timespec64,
|
||||
}
|
||||
|
||||
impl IoUring {
|
||||
pub(super) fn schedule_timeout_link(&self, timeout: Time) {
|
||||
let id = self.ring.id_raw();
|
||||
{
|
||||
let mut to = self.ring.cached_timeout_links.pop().unwrap_or_default();
|
||||
to.id = id;
|
||||
to.timespec.tv_sec = timeout.0.tv_sec as _;
|
||||
to.timespec.tv_nsec = timeout.0.tv_nsec as _;
|
||||
self.ring.schedule(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Task for TimeoutLinkTask {
|
||||
fn id(&self) -> u64 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn complete(self: Box<Self>, ring: &IoUringData, _res: i32) {
|
||||
ring.cached_timeout_links.push(self);
|
||||
}
|
||||
|
||||
fn encode(&self, sqe: &mut io_uring_sqe) {
|
||||
sqe.opcode = IORING_OP_LINK_TIMEOUT;
|
||||
sqe.u2.addr = &self.timespec as *const _ as _;
|
||||
sqe.len = 1;
|
||||
sqe.u3.timeout_flags = IORING_TIMEOUT_ABS;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue