1
0
Fork 0
forked from wry/wry

all: use tracy for tracing

This commit is contained in:
Julian Orth 2024-09-15 18:08:54 +02:00
parent 50186e764e
commit ccad3cf0fb
56 changed files with 647 additions and 171 deletions

73
Cargo.lock generated
View file

@ -210,7 +210,7 @@ dependencies = [
"js-sys", "js-sys",
"num-traits", "num-traits",
"wasm-bindgen", "wasm-bindgen",
"windows-targets 0.52.0", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -584,10 +584,12 @@ dependencies = [
"png", "png",
"rand", "rand",
"repc", "repc",
"rustc-demangle",
"serde", "serde",
"shaderc", "shaderc",
"smallvec", "smallvec",
"thiserror", "thiserror",
"tracy-client-sys",
"uapi", "uapi",
] ]
@ -1005,9 +1007,9 @@ dependencies = [
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]] [[package]]
name = "rustix" name = "rustix"
@ -1274,6 +1276,14 @@ dependencies = [
"serde_yaml", "serde_yaml",
] ]
[[package]]
name = "tracy-client-sys"
version = "0.24.0"
source = "git+https://github.com/mahkoh/rust_tracy_client.git?branch=jorth/debuginfod#0ffd3d3375039aa984189daf776f633312e890c8"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "uapi" name = "uapi"
version = "0.2.13" version = "0.2.13"
@ -1431,7 +1441,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets 0.52.0", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -1449,7 +1459,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.0", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -1469,17 +1479,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.0", "windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.0", "windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.0", "windows_i686_gnu 0.52.6",
"windows_i686_msvc 0.52.0", "windows_i686_gnullvm",
"windows_x86_64_gnu 0.52.0", "windows_i686_msvc 0.52.6",
"windows_x86_64_gnullvm 0.52.0", "windows_x86_64_gnu 0.52.6",
"windows_x86_64_msvc 0.52.0", "windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
] ]
[[package]] [[package]]
@ -1490,9 +1501,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -1502,9 +1513,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -1514,9 +1525,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -1526,9 +1543,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -1538,9 +1555,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -1550,9 +1567,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -1562,9 +1579,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.0" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "xmlparser" name = "xmlparser"

View file

@ -58,6 +58,14 @@ gpu-alloc-ash = "0.7.0"
serde = { version = "1.0.196", features = ["derive"] } serde = { version = "1.0.196", features = ["derive"] }
enum-map = "2.7.3" enum-map = "2.7.3"
png = "0.17.13" png = "0.17.13"
rustc-demangle = { version = "0.1.24", optional = true }
[dependencies.tracy-client-sys]
version = "0.24.0"
git = "https://github.com/mahkoh/rust_tracy_client.git"
branch = "jorth/debuginfod"
features = ["ondemand", "manual-lifetime"]
optional = true
[build-dependencies] [build-dependencies]
repc = "0.1.1" repc = "0.1.1"
@ -78,3 +86,4 @@ opt-level = 3
[features] [features]
rc_tracking = [] rc_tracking = []
it = [] it = []
tracy = ["dep:tracy-client-sys", "dep:rustc-demangle"]

View file

@ -146,16 +146,14 @@ impl Acceptor {
} }
let acc = Rc::new(Acceptor { socket }); let acc = Rc::new(Acceptor { socket });
let futures = vec![ let futures = vec![
state.eng.spawn(accept( state.eng.spawn(
acc.socket.secure.clone(), "secure acceptor",
state.clone(), accept(acc.socket.secure.clone(), state.clone(), ClientCaps::all()),
ClientCaps::all(), ),
)), state.eng.spawn(
state.eng.spawn(accept( "insecure acceptor",
acc.socket.insecure.clone(), accept(acc.socket.insecure.clone(), state.clone(), CAPS_DEFAULT),
state.clone(), ),
CAPS_DEFAULT,
)),
]; ];
state.acceptor.set(Some(acc.clone())); state.acceptor.set(Some(acc.clone()));
Ok((acc, futures)) Ok((acc, futures))

View file

@ -64,16 +64,21 @@ impl AsyncEngine {
} }
} }
pub fn spawn<T, F: Future<Output = T> + 'static>(self: &Rc<Self>, f: F) -> SpawnedFuture<T> { pub fn spawn<T, F: Future<Output = T> + 'static>(
self.spawn_(Phase::EventHandling, f) self: &Rc<Self>,
name: &str,
f: F,
) -> SpawnedFuture<T> {
self.spawn_(name, Phase::EventHandling, f)
} }
pub fn spawn2<T, F: Future<Output = T> + 'static>( pub fn spawn2<T, F: Future<Output = T> + 'static>(
self: &Rc<Self>, self: &Rc<Self>,
name: &str,
phase: Phase, phase: Phase,
f: F, f: F,
) -> SpawnedFuture<T> { ) -> SpawnedFuture<T> {
self.spawn_(phase, f) self.spawn_(name, phase, f)
} }
pub fn yield_now(self: &Rc<Self>) -> Yield { pub fn yield_now(self: &Rc<Self>) -> Yield {

View file

@ -1,6 +1,7 @@
use { use {
crate::{ crate::{
async_engine::{AsyncEngine, Phase}, async_engine::{AsyncEngine, Phase},
tracy::ZoneName,
utils::{ utils::{
numcell::NumCell, numcell::NumCell,
ptr_ext::{MutPtrExt, PtrExt}, ptr_ext::{MutPtrExt, PtrExt},
@ -95,6 +96,8 @@ struct Task<T, F: Future<Output = T>> {
data: UnsafeCell<TaskData<T, F>>, data: UnsafeCell<TaskData<T, F>>,
waker: Cell<Option<Waker>>, waker: Cell<Option<Waker>>,
queue: Rc<AsyncEngine>, queue: Rc<AsyncEngine>,
#[cfg_attr(not(feature = "tracy"), expect(dead_code))]
zone: ZoneName,
} }
pub(super) struct Runnable { pub(super) struct Runnable {
@ -122,6 +125,7 @@ impl Drop for Runnable {
impl AsyncEngine { impl AsyncEngine {
pub(super) fn spawn_<T, F: Future<Output = T>>( pub(super) fn spawn_<T, F: Future<Output = T>>(
self: &Rc<Self>, self: &Rc<Self>,
#[cfg_attr(not(feature = "tracy"), expect(unused_variables))] name: &str,
phase: Phase, phase: Phase,
f: F, f: F,
) -> SpawnedFuture<T> { ) -> SpawnedFuture<T> {
@ -134,6 +138,7 @@ impl AsyncEngine {
}), }),
waker: Cell::new(None), waker: Cell::new(None),
queue: self.clone(), queue: self.clone(),
zone: create_zone_name!("task:{}", name),
}); });
unsafe { unsafe {
f.schedule_run(); f.schedule_run();
@ -229,7 +234,11 @@ impl<T, F: Future<Output = T>> Task<T, F> {
let waker = Waker::from_raw(raw_waker); let waker = Waker::from_raw(raw_waker);
let mut ctx = Context::from_waker(&waker); let mut ctx = Context::from_waker(&waker);
if let Poll::Ready(d) = Pin::new_unchecked(&mut *data.future).poll(&mut ctx) { let poll = {
dynamic_zone!(self.zone);
Pin::new_unchecked(&mut *data.future).poll(&mut ctx)
};
if let Poll::Ready(d) = poll {
ManuallyDrop::drop(&mut data.future); ManuallyDrop::drop(&mut data.future);
ptr::write(&mut data.result, ManuallyDrop::new(d)); ptr::write(&mut data.result, ManuallyDrop::new(d));
self.state.or_assign(COMPLETED); self.state.or_assign(COMPLETED);

View file

@ -163,8 +163,14 @@ impl Debug for MetalBackend {
impl MetalBackend { impl MetalBackend {
async fn run(self: Rc<Self>) -> Result<(), MetalError> { async fn run(self: Rc<Self>) -> Result<(), MetalError> {
let _monitor = self.state.eng.spawn(self.clone().monitor_devices()); let _monitor = self
let _events = self.state.eng.spawn(self.clone().handle_libinput_events()); .state
.eng
.spawn("monitor devices", self.clone().monitor_devices());
let _events = self.state.eng.spawn(
"handle libinput events",
self.clone().handle_libinput_events(),
);
if let Err(e) = self.enumerate_devices() { if let Err(e) = self.enumerate_devices() {
return Err(MetalError::Enumerate(Box::new(e))); return Err(MetalError::Enumerate(Box::new(e)));
} }
@ -175,7 +181,7 @@ impl MetalBackend {
impl Backend for MetalBackend { impl Backend for MetalBackend {
fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn Error>>> { fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn Error>>> {
let slf = self.clone(); let slf = self.clone();
self.state.eng.spawn(async move { self.state.eng.spawn("metal backend", async move {
slf.run().await?; slf.run().await?;
Ok(()) Ok(())
}) })

View file

@ -13,6 +13,7 @@ use {
}, },
theme::Color, theme::Color,
time::Time, time::Time,
tracy::FrameName,
tree::OutputNode, tree::OutputNode,
utils::{errorfmt::ErrorFmt, oserror::OsError, transform_ext::TransformExt}, utils::{errorfmt::ErrorFmt, oserror::OsError, transform_ext::TransformExt},
video::{ video::{
@ -90,6 +91,8 @@ impl MetalConnector {
} }
pub async fn present_loop(self: Rc<Self>) { pub async fn present_loop(self: Rc<Self>) {
#[cfg_attr(not(feature = "tracy"), expect(unused_variables))]
let frame_name = FrameName::get(&self.kernel_id().to_string());
let mut cur_sec = 0; let mut cur_sec = 0;
let mut max = 0; let mut max = 0;
loop { loop {
@ -113,6 +116,7 @@ impl MetalConnector {
expected_sequence += 1; expected_sequence += 1;
} }
} }
frame!(frame_name);
if let Err(e) = self.present_once().await { if let Err(e) = self.present_once().await {
log::error!("Could not present: {}", ErrorFmt(e)); log::error!("Could not present: {}", ErrorFmt(e));
continue; continue;
@ -293,6 +297,7 @@ impl MetalConnector {
cursor: Option<&CursorProgramming>, cursor: Option<&CursorProgramming>,
new_fb: Option<&PresentFb>, new_fb: Option<&PresentFb>,
) -> Result<(), MetalError> { ) -> Result<(), MetalError> {
zone!("program_connector");
let mut changes = self.master.change(); let mut changes = self.master.change();
let mut try_async_flip = self.try_async_flip(); let mut try_async_flip = self.try_async_flip();
macro_rules! change { macro_rules! change {

View file

@ -1089,10 +1089,11 @@ fn create_connector(
presentation_is_zero_copy: Cell::new(false), presentation_is_zero_copy: Cell::new(false),
}); });
let futures = ConnectorFutures { let futures = ConnectorFutures {
_present: backend _present: backend.state.eng.spawn2(
.state "present loop",
.eng Phase::Present,
.spawn2(Phase::Present, slf.clone().present_loop()), slf.clone().present_loop(),
),
}; };
Ok((slf, futures)) Ok((slf, futures))
} }
@ -1791,10 +1792,10 @@ impl MetalBackend {
} }
} }
let drm_handler = self let drm_handler = self.state.eng.spawn(
.state "handle drm events",
.eng self.clone().handle_drm_events(slf.clone()),
.spawn(self.clone().handle_drm_events(slf.clone())); );
slf.dev.handle_events.handle_events.set(Some(drm_handler)); slf.dev.handle_events.handle_events.set(Some(drm_handler));
Ok(slf) Ok(slf)

View file

@ -249,7 +249,7 @@ pub async fn create(state: &Rc<State>) -> Result<Rc<XBackend>, XBackendError> {
impl Backend for XBackend { impl Backend for XBackend {
fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn Error>>> { fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn Error>>> {
let slf = self.clone(); let slf = self.clone();
self.state.eng.spawn(async move { self.state.eng.spawn("x backend", async move {
slf.run().await?; slf.run().await?;
Ok(()) Ok(())
}) })
@ -280,12 +280,19 @@ impl XBackend {
async fn run(self: Rc<Self>) -> Result<(), XBackendError> { async fn run(self: Rc<Self>) -> Result<(), XBackendError> {
self.query_devices(INPUT_DEVICE_ALL_MASTER).await?; self.query_devices(INPUT_DEVICE_ALL_MASTER).await?;
let _events = self.state.eng.spawn(self.clone().event_handler()); let _events = self
let _grab = self.state.eng.spawn(self.clone().grab_handler());
let _present = self
.state .state
.eng .eng
.spawn2(Phase::Present, self.clone().present_handler()); .spawn("x event handler", self.clone().event_handler());
let _grab = self
.state
.eng
.spawn("grab handler", self.clone().grab_handler());
let _present = self.state.eng.spawn2(
"present handler",
Phase::Present,
self.clone().present_handler(),
);
self.state.set_render_ctx(Some(self.ctx.clone())); self.state.set_render_ctx(Some(self.ctx.clone()));
self.state self.state

View file

@ -179,7 +179,7 @@ impl Clients {
data.objects.display.set(Some(display.clone())); data.objects.display.set(Some(display.clone()));
data.objects.add_client_object(display).expect(""); data.objects.add_client_object(display).expect("");
let client = ClientHolder { let client = ClientHolder {
_handler: global.eng.spawn(tasks::client(data.clone())), _handler: global.eng.spawn("client", tasks::client(data.clone())),
data: data.clone(), data: data.clone(),
}; };
log::info!( log::info!(

View file

@ -14,9 +14,16 @@ use {
}; };
pub async fn client(data: Rc<Client>) { pub async fn client(data: Rc<Client>) {
let mut recv = data.state.eng.spawn(receive(data.clone())).fuse(); let mut recv = data
.state
.eng
.spawn("client receive", receive(data.clone()))
.fuse();
let mut shutdown = data.shutdown.triggered().fuse(); let mut shutdown = data.shutdown.triggered().fuse();
let _send = data.state.eng.spawn2(Phase::PostLayout, send(data.clone())); let _send = data
.state
.eng
.spawn2("client send", Phase::PostLayout, send(data.clone()));
select! { select! {
_ = recv => { }, _ = recv => { },
_ = shutdown => { }, _ = shutdown => { },

View file

@ -255,6 +255,7 @@ impl CpuJob for CloseMemWork {
impl CpuWork for CloseMemWork { impl CpuWork for CloseMemWork {
fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> { fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> {
zone!("CloseMemWork");
self.fd.take(); self.fd.take();
unsafe { unsafe {
c::munmap(self.data as _, self.data.len()); c::munmap(self.data as _, self.data.len());

View file

@ -33,6 +33,7 @@ use {
sighand::{self, SighandError}, sighand::{self, SighandError},
state::{ConnectorData, IdleState, ScreenlockState, State, XWaylandState}, state::{ConnectorData, IdleState, ScreenlockState, State, XWaylandState},
tasks::{self, idle}, tasks::{self, idle},
tracy::enable_profiler,
tree::{ tree::{
container_layout, container_render_data, float_layout, float_titles, container_layout, container_render_data, float_layout, float_titles,
output_render_data, DisplayNode, NodeIds, OutputNode, TearingMode, VrrMode, output_render_data, DisplayNode, NodeIds, OutputNode, TearingMode, VrrMode,
@ -62,6 +63,7 @@ pub const MAX_EXTENTS: i32 = (1 << 22) - 1;
pub fn start_compositor(global: GlobalArgs, args: RunArgs) { pub fn start_compositor(global: GlobalArgs, args: RunArgs) {
let forker = create_forker(); let forker = create_forker();
let portal = portal::run_from_compositor(global.log_level.into()); let portal = portal::run_from_compositor(global.log_level.into());
enable_profiler();
let logger = Logger::install_compositor(global.log_level.into()); let logger = Logger::install_compositor(global.log_level.into());
let portal = match portal { let portal = match portal {
Ok(p) => Some(p), Ok(p) => Some(p),
@ -279,9 +281,12 @@ fn start_compositor2(
} }
let mut _portal = None; let mut _portal = None;
if let (Some(portal), Some(logger)) = (portal, &logger) { if let (Some(portal), Some(logger)) = (portal, &logger) {
_portal = Some(engine.spawn(portal.spawn(engine.clone(), ring.clone(), logger.clone()))); _portal = Some(engine.spawn(
"portal",
portal.spawn(engine.clone(), ring.clone(), logger.clone()),
));
} }
let _compositor = engine.spawn(start_compositor3(state.clone(), test_future)); let _compositor = engine.spawn("compositor", start_compositor3(state.clone(), test_future));
ring.run()?; ring.run()?;
state.clear(); state.clear();
Ok(()) Ok(())
@ -354,20 +359,65 @@ fn start_global_event_handlers(
let eng = &state.eng; let eng = &state.eng;
vec![ vec![
eng.spawn(tasks::handle_backend_events(state.clone())), eng.spawn(
eng.spawn(tasks::handle_slow_clients(state.clone())), "backend events",
eng.spawn(tasks::handle_hardware_cursor_tick(state.clone())), tasks::handle_backend_events(state.clone()),
eng.spawn2(Phase::Layout, container_layout(state.clone())), ),
eng.spawn2(Phase::PostLayout, container_render_data(state.clone())), eng.spawn("slow client", tasks::handle_slow_clients(state.clone())),
eng.spawn2(Phase::PostLayout, output_render_data(state.clone())), eng.spawn(
eng.spawn2(Phase::Layout, float_layout(state.clone())), "handware cursor tick",
eng.spawn2(Phase::PostLayout, float_titles(state.clone())), tasks::handle_hardware_cursor_tick(state.clone()),
eng.spawn2(Phase::PostLayout, idle(state.clone(), backend.clone())), ),
eng.spawn2(Phase::PostLayout, input_popup_positioning(state.clone())), eng.spawn2(
eng.spawn2(Phase::Present, perform_toplevel_screencasts(state.clone())), "container layout",
eng.spawn2(Phase::PostLayout, perform_screencast_realloc(state.clone())), Phase::Layout,
eng.spawn2(Phase::PostLayout, visualize_damage(state.clone())), container_layout(state.clone()),
eng.spawn(tasks::handle_slow_ei_clients(state.clone())), ),
eng.spawn2(
"container render",
Phase::PostLayout,
container_render_data(state.clone()),
),
eng.spawn2(
"output render",
Phase::PostLayout,
output_render_data(state.clone()),
),
eng.spawn2("float layout", Phase::Layout, float_layout(state.clone())),
eng.spawn2(
"float titles",
Phase::PostLayout,
float_titles(state.clone()),
),
eng.spawn2(
"idle",
Phase::PostLayout,
idle(state.clone(), backend.clone()),
),
eng.spawn2(
"input, popup positioning",
Phase::PostLayout,
input_popup_positioning(state.clone()),
),
eng.spawn2(
"toplevel screencast present",
Phase::Present,
perform_toplevel_screencasts(state.clone()),
),
eng.spawn2(
"screencast realloc",
Phase::PostLayout,
perform_screencast_realloc(state.clone()),
),
eng.spawn2(
"visualize damage",
Phase::PostLayout,
visualize_damage(state.clone()),
),
eng.spawn(
"slow ei clients",
tasks::handle_slow_ei_clients(state.clone()),
),
] ]
} }

View file

@ -447,7 +447,7 @@ impl ConfigProxyHandler {
let handler = { let handler = {
let timer = timer.clone(); let timer = timer.clone();
let slf = self.clone(); let slf = self.clone();
self.state.eng.spawn(async move { self.state.eng.spawn("config timer", async move {
loop { loop {
match timer.expired(&slf.state.ring).await { match timer.expired(&slf.state.ring).await {
Ok(_) => slf.send(&ServerMessage::TimerExpired { Ok(_) => slf.send(&ServerMessage::TimerExpired {
@ -1400,7 +1400,7 @@ impl ConfigProxyHandler {
let slf = self.clone(); let slf = self.clone();
let trigger = event.clone(); let trigger = event.clone();
let fd = fd.clone(); let fd = fd.clone();
let future = self.state.eng.spawn(async move { let future = self.state.eng.spawn("config fd poller", async move {
loop { loop {
trigger.triggered().await; trigger.triggered().await;
let res = slf.state.ring.poll(&fd, events).await.merge(); let res = slf.state.ring.poll(&fd, events).await.merge();

View file

@ -283,8 +283,11 @@ impl CpuWorker {
pending_job_data_cache: Default::default(), pending_job_data_cache: Default::default(),
}); });
Ok(Self { Ok(Self {
_completions_listener: eng.spawn(data.clone().wait_for_completions()), _completions_listener: eng.spawn(
_job_enqueuer: eng.spawn(data.clone().equeue_jobs()), "cpu worker completions",
data.clone().wait_for_completions(),
),
_job_enqueuer: eng.spawn("cpu worker enqueue", data.clone().equeue_jobs()),
data, data,
}) })
} }
@ -325,10 +328,13 @@ fn work(
async_jobs: Default::default(), async_jobs: Default::default(),
stopped: Cell::new(false), stopped: Cell::new(false),
}); });
let _stop_listener = worker.eng.spawn(worker.clone().handle_stop(stop)); let _stop_listener = worker
let _new_job_listener = worker
.eng .eng
.spawn(worker.clone().handle_new_jobs(new_jobs, have_new_jobs)); .spawn("stop listener", worker.clone().handle_stop(stop));
let _new_job_listener = worker.eng.spawn(
"new job listener",
worker.clone().handle_new_jobs(new_jobs, have_new_jobs),
);
if let Err(e) = worker.ring.run() { if let Err(e) = worker.ring.run() {
panic!("io_uring failed: {}", ErrorFmt(e)); panic!("io_uring failed: {}", ErrorFmt(e));
} }

View file

@ -35,6 +35,7 @@ impl ImgCopyWork {
impl CpuWork for ImgCopyWork { impl CpuWork for ImgCopyWork {
fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> { fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> {
zone!("ImgCopyWork");
for rect in &self.rects { for rect in &self.rects {
let mut offset = rect.y1() * self.stride + rect.x1() * self.bpp; let mut offset = rect.y1() * self.stride + rect.x1() * self.bpp;
if rect.width() == self.width { if rect.width() == self.width {

View file

@ -102,7 +102,7 @@ impl AsyncCpuWork for ReadWriteWorkConfig {
completion: WorkCompletion, completion: WorkCompletion,
) -> SpawnedFuture<CompletedWork> { ) -> SpawnedFuture<CompletedWork> {
let ring = ring.clone(); let ring = ring.clone();
eng.spawn(async move { eng.spawn("shm read/write", async move {
let res = loop { let res = loop {
if self.cancel.cancelled.load(Relaxed) { if self.cancel.cancelled.load(Relaxed) {
break Err(ReadWriteJobError::Cancelled); break Err(ReadWriteJobError::Cancelled);

View file

@ -62,7 +62,7 @@ impl AsyncCpuWork for AsyncWork {
completion: WorkCompletion, completion: WorkCompletion,
) -> SpawnedFuture<CompletedWork> { ) -> SpawnedFuture<CompletedWork> {
let ring = ring.clone(); let ring = ring.clone();
eng.spawn(async move { eng.spawn("", async move {
let mut buf = [0; 8]; let mut buf = [0; 8];
let res = ring let res = ring
.read_no_cancel(self.0.borrow(), 0, &mut buf, |_| ()) .read_no_cancel(self.0.borrow(), 0, &mut buf, |_| ())
@ -90,7 +90,7 @@ fn run(cancel: bool) {
work: Work(eventfd.clone()), work: Work(eventfd.clone()),
cancel, cancel,
})); }));
let _fut1 = eng.spawn(async move { let _fut1 = eng.spawn("", async move {
wheel.timeout(1).await.unwrap(); wheel.timeout(1).await.unwrap();
if cancel { if cancel {
drop(pending_job); drop(pending_job);
@ -99,7 +99,7 @@ fn run(cancel: bool) {
pending::<()>().await; pending::<()>().await;
} }
}); });
let _fut2 = eng.spawn(async move { let _fut2 = eng.spawn("", async move {
ae.triggered().await; ae.triggered().await;
ring2.stop(); ring2.stop();
}); });

View file

@ -39,10 +39,14 @@ impl Auth {
} }
log::info!("{}: Authenticated", self.socket.bus_name); log::info!("{}: Authenticated", self.socket.bus_name);
self.socket.incoming.set(Some( self.socket.incoming.set(Some(
self.socket.eng.spawn(handle_incoming(self.socket.clone())), self.socket
.eng
.spawn("dbus incoming", handle_incoming(self.socket.clone())),
)); ));
self.socket.outgoing_.set(Some( self.socket.outgoing_.set(Some(
self.socket.eng.spawn(handle_outgoing(self.socket.clone())), self.socket
.eng
.spawn("dbus outgoing", handle_outgoing(self.socket.clone())),
)); ));
self.socket.auth.take(); self.socket.auth.take();
} }

View file

@ -84,7 +84,7 @@ async fn connect(
} }
}, },
); );
let future = eng.spawn(handle_auth(socket.clone())); let future = eng.spawn("dbus auth", handle_auth(socket.clone()));
socket.auth.set(Some(future)); socket.auth.set(Some(future));
Ok(socket) Ok(socket)
} }

View file

@ -126,9 +126,10 @@ impl EiAcceptor {
return Err(EiAcceptorError::ListenFailed(e.into())); return Err(EiAcceptorError::ListenFailed(e.into()));
} }
let acc = Rc::new(EiAcceptor { socket }); let acc = Rc::new(EiAcceptor { socket });
let future = state let future = state.eng.spawn(
.eng "ei accept",
.spawn(accept(acc.socket.insecure.clone(), state.clone())); accept(acc.socket.insecure.clone(), state.clone()),
);
Ok((acc, future)) Ok((acc, future))
} }

View file

@ -120,7 +120,9 @@ impl EiClients {
handshake.send_handshake_version(); handshake.send_handshake_version();
data.objects.add_handshake(&handshake); data.objects.add_handshake(&handshake);
let client = EiClientHolder { let client = EiClientHolder {
_handler: global.eng.spawn(ei_tasks::ei_client(data.clone())), _handler: global
.eng
.spawn("ei client", ei_tasks::ei_client(data.clone())),
data: data.clone(), data: data.clone(),
}; };
log::info!( log::info!(

View file

@ -16,9 +16,16 @@ use {
}; };
pub async fn ei_client(data: Rc<EiClient>) { pub async fn ei_client(data: Rc<EiClient>) {
let mut recv = data.state.eng.spawn(receive(data.clone())).fuse(); let mut recv = data
.state
.eng
.spawn("ei receive", receive(data.clone()))
.fuse();
let mut shutdown = data.shutdown.triggered().fuse(); let mut shutdown = data.shutdown.triggered().fuse();
let _send = data.state.eng.spawn2(Phase::PostLayout, send(data.clone())); let _send = data
.state
.eng
.spawn2("ei send", Phase::PostLayout, send(data.clone()));
select! { select! {
_ = recv => { }, _ = recv => { },
_ = shutdown => { }, _ = shutdown => { },

View file

@ -109,13 +109,20 @@ impl ForkerProxy {
pub fn install(self: &Rc<Self>, state: &Rc<State>) { pub fn install(self: &Rc<Self>, state: &Rc<State>) {
state.forker.set(Some(self.clone())); state.forker.set(Some(self.clone()));
self.task_proc.set(Some( self.task_proc.set(Some(state.eng.spawn(
state.eng.spawn(self.clone().check_process(state.clone())), "forker check process",
self.clone().check_process(state.clone()),
)));
self.task_in.set(Some(
state
.eng
.spawn("forker incoming", self.clone().incoming(state.clone())),
));
self.task_out.set(Some(
state
.eng
.spawn("forker outgoing", self.clone().outgoing(state.clone())),
)); ));
self.task_in
.set(Some(state.eng.spawn(self.clone().incoming(state.clone()))));
self.task_out
.set(Some(state.eng.spawn(self.clone().outgoing(state.clone()))));
} }
pub fn setenv(&self, key: &[u8], val: &[u8]) { pub fn setenv(&self, key: &[u8], val: &[u8]) {
@ -353,8 +360,8 @@ impl Forker {
outgoing: Default::default(), outgoing: Default::default(),
pending_spawns: Default::default(), pending_spawns: Default::default(),
}); });
let _f1 = ae.spawn(forker.clone().incoming()); let _f1 = ae.spawn("forker incoming", forker.clone().incoming());
let _f2 = ae.spawn(forker.clone().outgoing()); let _f2 = ae.spawn("forker outgoing", forker.clone().outgoing());
let _ = ring.run(); let _ = ring.run();
std::process::exit(1); std::process::exit(1);
} }
@ -462,7 +469,7 @@ impl Forker {
} }
drop(write); drop(write);
let slf = self.clone(); let slf = self.clone();
let spawn = self.ae.spawn(async move { let spawn = self.ae.spawn("await spawn", async move {
let read = Rc::new(read); let read = Rc::new(read);
if let Err(e) = slf.ring.readable(&read).await { if let Err(e) = slf.ring.readable(&read).await {
log::error!( log::error!(

View file

@ -251,6 +251,7 @@ struct AllocWork {
impl CpuWork for AllocWork { impl CpuWork for AllocWork {
fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> { fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> {
zone!("AllocWork");
let r = do_alloc( let r = do_alloc(
&mut self.allocator.lock(), &mut self.allocator.lock(),
&self.device, &self.device,
@ -303,6 +304,7 @@ struct FreeWork {
impl CpuWork for FreeWork { impl CpuWork for FreeWork {
fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> { fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> {
zone!("FreeWork");
let ua = self.allocation.take().unwrap(); let ua = self.allocation.take().unwrap();
unsafe { unsafe {
do_free(&mut self.allocator.lock(), &self.device, ua.block, ua.ptr); do_free(&mut self.allocator.lock(), &self.device, ua.block, ua.ptr);

View file

@ -274,6 +274,7 @@ impl VulkanRenderer {
} }
fn collect_memory(&self, opts: &[GfxApiOpt]) { fn collect_memory(&self, opts: &[GfxApiOpt]) {
zone!("collect_memory");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
memory.sample.clear(); memory.sample.clear();
for cmd in opts { for cmd in opts {
@ -296,6 +297,7 @@ impl VulkanRenderer {
} }
fn begin_command_buffer(&self, buf: CommandBuffer) -> Result<(), VulkanError> { fn begin_command_buffer(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
zone!("begin_command_buffer");
let begin_info = let begin_info =
CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT); CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT);
unsafe { unsafe {
@ -307,6 +309,7 @@ impl VulkanRenderer {
} }
fn initial_barriers(&self, buf: CommandBuffer, fb: &VulkanImage) { fn initial_barriers(&self, buf: CommandBuffer, fb: &VulkanImage) {
zone!("initial_barriers");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let memory = &mut *memory; let memory = &mut *memory;
memory.image_barriers.clear(); memory.image_barriers.clear();
@ -355,6 +358,7 @@ impl VulkanRenderer {
} }
fn begin_rendering(&self, buf: CommandBuffer, fb: &VulkanImage, clear: Option<&Color>) { fn begin_rendering(&self, buf: CommandBuffer, fb: &VulkanImage, clear: Option<&Color>) {
zone!("begin_rendering");
let rendering_attachment_info = { let rendering_attachment_info = {
let mut rai = RenderingAttachmentInfo::default() let mut rai = RenderingAttachmentInfo::default()
.image_view(fb.render_view.unwrap_or(fb.texture_view)) .image_view(fb.render_view.unwrap_or(fb.texture_view))
@ -388,6 +392,7 @@ impl VulkanRenderer {
} }
fn set_viewport(&self, buf: CommandBuffer, fb: &VulkanImage) { fn set_viewport(&self, buf: CommandBuffer, fb: &VulkanImage) {
zone!("set_viewport");
let viewport = Viewport { let viewport = Viewport {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
@ -419,6 +424,7 @@ impl VulkanRenderer {
fb: &VulkanImage, fb: &VulkanImage,
opts: &[GfxApiOpt], opts: &[GfxApiOpt],
) -> Result<(), VulkanError> { ) -> Result<(), VulkanError> {
zone!("record_draws");
let pipelines = self.get_or_create_pipelines(fb.format.vk_format)?; let pipelines = self.get_or_create_pipelines(fb.format.vk_format)?;
let dev = &self.device.device; let dev = &self.device.device;
let mut current_pipeline = None; let mut current_pipeline = None;
@ -519,12 +525,14 @@ impl VulkanRenderer {
} }
fn end_rendering(&self, buf: CommandBuffer) { fn end_rendering(&self, buf: CommandBuffer) {
zone!("end_rendering");
unsafe { unsafe {
self.device.device.cmd_end_rendering(buf); self.device.device.cmd_end_rendering(buf);
} }
} }
fn copy_bridge_to_dmabuf(&self, buf: CommandBuffer, fb: &VulkanImage) { fn copy_bridge_to_dmabuf(&self, buf: CommandBuffer, fb: &VulkanImage) {
zone!("copy_bridge_to_dmabuf");
let Some(bridge) = &fb.bridge else { let Some(bridge) = &fb.bridge else {
return; return;
}; };
@ -584,6 +592,7 @@ impl VulkanRenderer {
} }
fn final_barriers(&self, buf: CommandBuffer, fb: &VulkanImage) { fn final_barriers(&self, buf: CommandBuffer, fb: &VulkanImage) {
zone!("final_barriers");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let memory = &mut *memory; let memory = &mut *memory;
memory.image_barriers.clear(); memory.image_barriers.clear();
@ -625,6 +634,7 @@ impl VulkanRenderer {
} }
fn end_command_buffer(&self, buf: CommandBuffer) -> Result<(), VulkanError> { fn end_command_buffer(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
zone!("end_command_buffer");
unsafe { unsafe {
self.device self.device
.device .device
@ -634,6 +644,7 @@ impl VulkanRenderer {
} }
fn create_wait_semaphores(&self, fb: &VulkanImage) -> Result<(), VulkanError> { fn create_wait_semaphores(&self, fb: &VulkanImage) -> Result<(), VulkanError> {
zone!("create_wait_semaphores");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let memory = &mut *memory; let memory = &mut *memory;
memory.wait_semaphore_infos.clear(); memory.wait_semaphore_infos.clear();
@ -658,6 +669,7 @@ impl VulkanRenderer {
match sync { match sync {
AcquireSync::None => {} AcquireSync::None => {}
AcquireSync::Implicit { .. } => { AcquireSync::Implicit { .. } => {
zone!("import implicit");
for plane in &buf.template.dmabuf.planes { for plane in &buf.template.dmabuf.planes {
let fd = dma_buf_export_sync_file(&plane.fd, flag) let fd = dma_buf_export_sync_file(&plane.fd, flag)
.map_err(VulkanError::IoctlExportSyncFile)?; .map_err(VulkanError::IoctlExportSyncFile)?;
@ -694,6 +706,7 @@ impl VulkanRenderer {
} }
fn import_release_semaphore(&self, fb: &VulkanImage) { fn import_release_semaphore(&self, fb: &VulkanImage) {
zone!("import_release_semaphore");
let memory = &mut *self.memory.borrow_mut(); let memory = &mut *self.memory.borrow_mut();
let sync_file = match memory.release_sync_file.as_ref() { let sync_file = match memory.release_sync_file.as_ref() {
Some(sync_file) => sync_file, Some(sync_file) => sync_file,
@ -727,6 +740,7 @@ impl VulkanRenderer {
} }
fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> { fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
zone!("submit");
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let release_fence = self.device.create_fence()?; let release_fence = self.device.create_fence()?;
let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(buf); let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(buf);
@ -743,6 +757,7 @@ impl VulkanRenderer {
) )
.map_err(VulkanError::Submit)?; .map_err(VulkanError::Submit)?;
} }
zone!("export_sync_file");
let release_sync_file = match release_fence.export_sync_file() { let release_sync_file = match release_fence.export_sync_file() {
Ok(s) => Some(s), Ok(s) => Some(s),
Err(e) => { Err(e) => {
@ -761,6 +776,7 @@ impl VulkanRenderer {
} }
fn create_pending_frame(self: &Rc<Self>, buf: Rc<VulkanCommandBuffer>) { fn create_pending_frame(self: &Rc<Self>, buf: Rc<VulkanCommandBuffer>) {
zone!("create_pending_frame");
let point = self.allocate_point(); let point = self.allocate_point();
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
let frame = Rc::new(PendingFrame { let frame = Rc::new(PendingFrame {
@ -773,12 +789,15 @@ impl VulkanRenderer {
_release_fence: memory.release_fence.take(), _release_fence: memory.release_fence.take(),
}); });
self.pending_frames.set(frame.point, frame.clone()); self.pending_frames.set(frame.point, frame.clone());
let future = self.eng.spawn(await_release( let future = self.eng.spawn(
memory.release_sync_file.clone(), "await release",
self.ring.clone(), await_release(
frame.clone(), memory.release_sync_file.clone(),
self.clone(), self.ring.clone(),
)); frame.clone(),
self.clone(),
),
);
frame.waiter.set(Some(future)); frame.waiter.set(Some(future));
} }
@ -976,6 +995,7 @@ impl VulkanRenderer {
opts: &[GfxApiOpt], opts: &[GfxApiOpt],
clear: Option<&Color>, clear: Option<&Color>,
) -> Result<Option<SyncFile>, VulkanError> { ) -> Result<Option<SyncFile>, VulkanError> {
zone!("execute");
let res = self.try_execute(fb, opts, clear); let res = self.try_execute(fb, opts, clear);
let sync_file = { let sync_file = {
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.borrow_mut();
@ -989,6 +1009,7 @@ impl VulkanRenderer {
} }
pub(super) fn allocate_command_buffer(&self) -> Result<Rc<VulkanCommandBuffer>, VulkanError> { pub(super) fn allocate_command_buffer(&self) -> Result<Rc<VulkanCommandBuffer>, VulkanError> {
zone!("allocate_command_buffer");
let buf = match self.command_buffers.pop() { let buf = match self.command_buffers.pop() {
Some(b) => b, Some(b) => b,
_ => { _ => {
@ -1000,6 +1021,7 @@ impl VulkanRenderer {
} }
fn allocate_semaphore(&self) -> Result<Rc<VulkanSemaphore>, VulkanError> { fn allocate_semaphore(&self) -> Result<Rc<VulkanSemaphore>, VulkanError> {
zone!("allocate_semaphore");
let semaphore = match self.wait_semaphores.pop() { let semaphore = match self.wait_semaphores.pop() {
Some(s) => s, Some(s) => s,
_ => self.device.create_semaphore()?, _ => self.device.create_semaphore()?,

View file

@ -37,6 +37,7 @@ impl VulkanDevice {
impl VulkanSemaphore { impl VulkanSemaphore {
pub fn import_sync_file(&self, sync_file: OwnedFd) -> Result<(), VulkanError> { pub fn import_sync_file(&self, sync_file: OwnedFd) -> Result<(), VulkanError> {
zone!("import_sync_file");
let fd_info = ImportSemaphoreFdInfoKHR::default() let fd_info = ImportSemaphoreFdInfoKHR::default()
.fd(sync_file.raw()) .fd(sync_file.raw())
.flags(SemaphoreImportFlags::TEMPORARY) .flags(SemaphoreImportFlags::TEMPORARY)

View file

@ -164,14 +164,10 @@ impl VulkanShmImage {
else { else {
return Ok(()); return Ok(());
}; };
let future = img.renderer.eng.spawn(await_upload( let future = img.renderer.eng.spawn(
point, "await upload",
img.clone(), await_upload(point, img.clone(), cmd, sync_file, fence, staging),
cmd, );
sync_file,
fence,
staging,
));
img.renderer.pending_uploads.set(point, future); img.renderer.pending_uploads.set(point, future);
Ok(()) Ok(())
} }
@ -519,13 +515,10 @@ impl VulkanShmImage {
else { else {
return Ok(()); return Ok(());
}; };
let future = img.renderer.eng.spawn(await_async_upload( let future = img.renderer.eng.spawn(
point, "await async upload",
img.clone(), await_async_upload(point, img.clone(), cmd, fence, sync_file),
cmd, );
fence,
sync_file,
));
img.renderer.pending_uploads.set(point, future); img.renderer.pending_uploads.set(point, future);
Ok(()) Ok(())
} }

View file

@ -72,7 +72,11 @@ impl ExtIdleNotifierV1RequestHandler for ExtIdleNotifierV1 {
}); });
track!(self.client, notification); track!(self.client, notification);
self.client.add_client_obj(&notification)?; self.client.add_client_obj(&notification)?;
let future = self.client.state.eng.spawn(run(notification.clone())); let future = self
.client
.state
.eng
.spawn("idle notifier", run(notification.clone()));
notification.task.set(Some(future)); notification.task.set(Some(future));
Ok(()) Ok(())
} }

View file

@ -270,7 +270,7 @@ impl WlSeatGlobal {
}); });
slf.pointer_cursor.set_owner(slf.clone()); slf.pointer_cursor.set_owner(slf.clone());
let seat = slf.clone(); let seat = slf.clone();
let future = state.eng.spawn(async move { let future = state.eng.spawn("seat handler", async move {
loop { loop {
seat.tree_changed.triggered().await; seat.tree_changed.triggered().await;
seat.state.tree_changed_sent.set(false); seat.state.tree_changed_sent.set(false);

View file

@ -17,7 +17,7 @@ fn cancel(timeout: bool) {
let wheel = Wheel::new(&eng, &ring).unwrap(); let wheel = Wheel::new(&eng, &ring).unwrap();
let queue = Rc::new(AsyncQueue::new()); let queue = Rc::new(AsyncQueue::new());
let queue2 = queue.clone(); let queue2 = queue.clone();
let _fut1 = eng.spawn(async move { let _fut1 = eng.spawn("", async move {
let (read, _write) = uapi::pipe().unwrap(); let (read, _write) = uapi::pipe().unwrap();
let mut buf = [10]; let mut buf = [10];
let res = ring let res = ring
@ -29,7 +29,7 @@ fn cancel(timeout: bool) {
)); ));
ring.stop(); ring.stop();
}); });
let _fut2 = eng.spawn(async move { let _fut2 = eng.spawn("", async move {
let id = queue2.pop().await; let id = queue2.pop().await;
if timeout { if timeout {
wheel.timeout(1).await.unwrap(); wheel.timeout(1).await.unwrap();

View file

@ -143,7 +143,7 @@ fn run_test(it_run: &ItRun, test: &'static dyn TestCase, cfg: Rc<TestConfig>) {
let errors = errors2.clone(); let errors = errors2.clone();
Box::new(async move { Box::new(async move {
let future: Pin<_> = test.run(testrun.clone()).into(); let future: Pin<_> = test.run(testrun.clone()).into();
let future = state.eng.spawn2(Phase::Present, future); let future = state.eng.spawn2("testrun", Phase::Present, future);
let timeout = state.wheel.timeout(500000); let timeout = state.wheel.timeout(500000);
match future::select(future, timeout).await { match future::select(future, timeout).await {
Either::Left((Ok(..), _)) => {} Either::Left((Ok(..), _)) => {}

View file

@ -271,7 +271,7 @@ where
impl Backend for TestBackend { impl Backend for TestBackend {
fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn std::error::Error>>> { fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn std::error::Error>>> {
let future = (self.test_future)(&self.state); let future = (self.test_future)(&self.state);
self.state.eng.spawn(async move { self.state.eng.spawn("", async move {
let future: Pin<_> = future.into(); let future: Pin<_> = future.into();
future.await; future.await;
Ok(()) Ok(())

View file

@ -147,6 +147,7 @@ impl TestTransport {
pub fn init(self: &Rc<Self>) { pub fn init(self: &Rc<Self>) {
self.incoming.set(Some( self.incoming.set(Some(
self.run.state.eng.spawn( self.run.state.eng.spawn(
"",
Incoming { Incoming {
tc: self.clone(), tc: self.clone(),
buf: BufFdIn::new(&self.socket, &self.run.state.ring), buf: BufFdIn::new(&self.socket, &self.run.state.ring),
@ -156,6 +157,7 @@ impl TestTransport {
)); ));
self.outgoing.set(Some( self.outgoing.set(Some(
self.run.state.eng.spawn( self.run.state.eng.spawn(
"",
Outgoing { Outgoing {
tc: self.clone(), tc: self.clone(),
buf: BufFdOut::new(&self.socket, &self.run.state.ring), buf: BufFdOut::new(&self.socket, &self.run.state.ring),

View file

@ -43,6 +43,8 @@
mod macros; mod macros;
#[macro_use] #[macro_use]
mod leaks; mod leaks;
#[macro_use]
mod tracy;
mod acceptor; mod acceptor;
mod allocator; mod allocator;
mod async_engine; mod async_engine;

View file

@ -347,8 +347,12 @@ impl PwConHolder {
data.send_hello(); data.send_hello();
data.send_properties(); data.send_properties();
let con = Rc::new(PwConHolder { let con = Rc::new(PwConHolder {
outgoing: Cell::new(Some(eng.spawn(data.clone().handle_outgoing()))), outgoing: Cell::new(Some(
incoming: Cell::new(Some(eng.spawn(data.clone().handle_incoming()))), eng.spawn("pw outgoing", data.clone().handle_outgoing()),
)),
incoming: Cell::new(Some(
eng.spawn("pw incoming", data.clone().handle_incoming()),
)),
con: data, con: data,
}); });
con.con.holder.set(Rc::downgrade(&con)); con.con.holder.set(Rc::downgrade(&con));

View file

@ -745,7 +745,9 @@ impl PwClientNode {
let typed = map.typed::<pw_node_activation>(); let typed = map.typed::<pw_node_activation>();
self.activation.set(Some(typed.clone())); self.activation.set(Some(typed.clone()));
self.transport_in.set(Some( self.transport_in.set(Some(
self.con.eng.spawn(self.clone().transport_in(typed, readfd)), self.con
.eng
.spawn("pw transport in", self.clone().transport_in(typed, readfd)),
)); ));
self.transport_out.set(Some(writefd)); self.transport_out.set(Some(writefd));
Ok(()) Ok(())

View file

@ -76,7 +76,7 @@ pub struct PortalStartup {
impl PortalStartup { impl PortalStartup {
pub async fn spawn(self, eng: Rc<AsyncEngine>, ring: Rc<IoUring>, logger: Arc<Logger>) { pub async fn spawn(self, eng: Rc<AsyncEngine>, ring: Rc<IoUring>, logger: Arc<Logger>) {
let f1 = eng.spawn({ let f1 = eng.spawn("check portal exit code", {
let ring = ring.clone(); let ring = ring.clone();
async move { async move {
if let Err(e) = ring.readable(&self.pidfd).await { if let Err(e) = ring.readable(&self.pidfd).await {
@ -103,7 +103,7 @@ impl PortalStartup {
} }
} }
}); });
let f2 = eng.spawn({ let f2 = eng.spawn("portal logger", {
let ring = ring.clone(); let ring = ring.clone();
let logger = logger.clone(); let logger = logger.clone();
async move { async move {
@ -155,7 +155,10 @@ fn run(logger: Arc<Logger>, freestanding: bool) {
fatal!("Could not create an IO-uring: {}", ErrorFmt(e)); fatal!("Could not create an IO-uring: {}", ErrorFmt(e));
} }
}; };
let _f = eng.spawn(run_async(eng.clone(), ring.clone(), logger, freestanding)); let _f = eng.spawn(
"portal",
run_async(eng.clone(), ring.clone(), logger, freestanding),
);
if let Err(e) = ring.run() { if let Err(e) = ring.run() {
fatal!("The IO-uring returned an error: {}", ErrorFmt(e)); fatal!("The IO-uring returned an error: {}", ErrorFmt(e));
} }

View file

@ -579,11 +579,11 @@ impl WindowData {
fractional_scale, fractional_scale,
seats: Default::default(), seats: Default::default(),
}); });
data.render_task.set(Some( data.render_task.set(Some(dpy.state.eng.spawn2(
dpy.state "render",
.eng Phase::Present,
.spawn2(Phase::Present, data.clone().render_task()), data.clone().render_task(),
)); )));
data.fractional_scale.owner.set(Some(data.clone())); data.fractional_scale.owner.set(Some(data.clone()));
data data
} }

View file

@ -64,12 +64,16 @@ impl SecurityContextAcceptors {
close_future: Cell::new(None), close_future: Cell::new(None),
}); });
log::info!("Creating security acceptor {acceptor}"); log::info!("Creating security acceptor {acceptor}");
acceptor acceptor.listen_future.set(Some(
.listen_future state
.set(Some(state.eng.spawn(acceptor.clone().accept()))); .eng
acceptor .spawn("security accept", acceptor.clone().accept()),
.close_future ));
.set(Some(state.eng.spawn(acceptor.clone().close()))); acceptor.close_future.set(Some(
state
.eng
.spawn("security await close", acceptor.clone().close()),
));
self.acceptors.set(acceptor.id, acceptor); self.acceptors.set(acceptor.id, acceptor);
} }
} }

View file

@ -32,7 +32,7 @@ pub fn install(
Ok(fd) => Rc::new(fd), Ok(fd) => Rc::new(fd),
Err(e) => return Err(SighandError::CreateFailed(e.into())), Err(e) => return Err(SighandError::CreateFailed(e.into())),
}; };
Ok(eng.spawn(handle_signals(fd, ring.clone()))) Ok(eng.spawn("signal handler", handle_signals(fd, ring.clone())))
} }
async fn handle_signals(fd: Rc<OwnedFd>, ring: Rc<IoUring>) { async fn handle_signals(fd: Rc<OwnedFd>, ring: Rc<IoUring>) {

View file

@ -729,7 +729,7 @@ impl State {
} }
let mut handler = self.xwayland.handler.borrow_mut(); let mut handler = self.xwayland.handler.borrow_mut();
if handler.is_none() { if handler.is_none() {
*handler = Some(self.eng.spawn(xwayland::manage(self.clone()))); *handler = Some(self.eng.spawn("xwayland", xwayland::manage(self.clone())));
} }
} }

View file

@ -41,7 +41,7 @@ pub fn handle(state: &Rc<State>, connector: &Rc<dyn Connector>) {
state: state.clone(), state: state.clone(),
data: data.clone(), data: data.clone(),
}; };
let future = state.eng.spawn(oh.handle()); let future = state.eng.spawn("connector handler", oh.handle());
data.handler.set(Some(future)); data.handler.set(Some(future));
if state.connectors.set(id, data).is_some() { if state.connectors.set(id, data).is_some() {
panic!("Connector id has been reused"); panic!("Connector id has been reused");
@ -141,7 +141,10 @@ impl ConnectorHandler {
&self.data, &self.data,
&desired_state, &desired_state,
)); ));
let _schedule = self.state.eng.spawn(schedule.clone().drive()); let _schedule = self
.state
.eng
.spawn("output schedule", schedule.clone().drive());
let on = Rc::new(OutputNode { let on = Rc::new(OutputNode {
id: self.state.node_ids.next(), id: self.state.node_ids.next(),
workspaces: Default::default(), workspaces: Default::default(),

View file

@ -34,7 +34,7 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn BackendDrmDevice>) {
state: state.clone(), state: state.clone(),
data: data.clone(), data: data.clone(),
}; };
let future = state.eng.spawn(oh.handle()); let future = state.eng.spawn("drmdev handler", oh.handle());
data.handler.set(Some(future)); data.handler.set(Some(future));
if state.drm_devs.set(id, data).is_some() { if state.drm_devs.set(id, data).is_some() {
panic!("Drm device id has been reused"); panic!("Drm device id has been reused");

View file

@ -35,7 +35,7 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
data: data.clone(), data: data.clone(),
ae: ae.clone(), ae: ae.clone(),
}; };
let handler = state.eng.spawn(oh.handle()); let handler = state.eng.spawn("input dev handler", oh.handle());
state.input_device_handlers.borrow_mut().insert( state.input_device_handlers.borrow_mut().insert(
dev.id(), dev.id(),
InputDeviceData { InputDeviceData {

View file

@ -122,7 +122,7 @@ where
}; };
let eng2 = eng.clone(); let eng2 = eng.clone();
let ring2 = ring.clone(); let ring2 = ring.clone();
let _f = eng.spawn(async move { let _f = eng.spawn("tool client", async move {
let tc = match ToolClient::try_new(logger, eng2, ring2).await { let tc = match ToolClient::try_new(logger, eng2, ring2).await {
Ok(tc) => tc, Ok(tc) => tc,
Err(e) => handle_error(e), Err(e) => handle_error(e),
@ -199,6 +199,7 @@ impl ToolClient {
}); });
slf.incoming.set(Some( slf.incoming.set(Some(
slf.eng.spawn( slf.eng.spawn(
"tool client incoming",
Incoming { Incoming {
tc: slf.clone(), tc: slf.clone(),
buf: BufFdIn::new(&socket, &slf.ring), buf: BufFdIn::new(&socket, &slf.ring),
@ -208,6 +209,7 @@ impl ToolClient {
)); ));
slf.outgoing.set(Some( slf.outgoing.set(Some(
slf.eng.spawn( slf.eng.spawn(
"tool client outgoing",
Outgoing { Outgoing {
tc: slf.clone(), tc: slf.clone(),
buf: BufFdOut::new(&socket, &slf.ring), buf: BufFdOut::new(&socket, &slf.ring),
@ -239,7 +241,7 @@ impl ToolClient {
if let Some(res) = res { if let Some(res) = res {
let id = slf.next_id.fetch_add(1); let id = slf.next_id.fetch_add(1);
let slf2 = slf.clone(); let slf2 = slf.clone();
let future = slf.eng.spawn(async move { let future = slf.eng.spawn("tool client handler", async move {
res.await; res.await;
slf2.pending_futures.borrow_mut().remove(&id); slf2.pending_futures.borrow_mut().remove(&id);
}); });

15
src/tracy.rs Normal file
View file

@ -0,0 +1,15 @@
#[cfg(feature = "tracy")]
#[macro_use]
mod tracy_impl;
#[cfg(feature = "tracy")]
use tracy_impl as imp;
#[cfg(not(feature = "tracy"))]
#[macro_use]
mod tracy_noop;
#[cfg(not(feature = "tracy"))]
use tracy_noop as imp;
pub use imp::{enable_profiler, FrameName, ZoneName};

212
src/tracy/tracy_impl.rs Normal file
View file

@ -0,0 +1,212 @@
use {
ahash::AHashMap,
parking_lot::Mutex,
std::{
ffi::{CStr, CString},
ptr,
sync::{
atomic::{AtomicBool, Ordering::Relaxed},
LazyLock,
},
},
tracy_client_sys::{
___tracy_c_zone_context, ___tracy_emit_frame_mark_end, ___tracy_emit_frame_mark_start,
___tracy_emit_zone_end, ___tracy_source_location_data, ___tracy_startup_profiler,
},
};
#[derive(Copy, Clone)]
pub struct ZoneName {
data: &'static ZoneNameData,
}
struct ZoneNameData {
_name: CString,
loc: ___tracy_source_location_data,
}
unsafe impl Sync for ZoneNameData {}
unsafe impl Send for ZoneNameData {}
static CACHE: LazyLock<Mutex<AHashMap<String, ZoneName>>> = LazyLock::new(|| Default::default());
impl ZoneName {
pub fn __get(name: &str) -> Self {
let mut cache = CACHE.lock();
if let Some(span) = cache.get(name) {
return *span;
}
let cname = CString::new(name).unwrap();
let span = ZoneName {
data: Box::leak(Box::new(ZoneNameData {
loc: ___tracy_source_location_data {
name: cname.as_ptr(),
function: ptr::null(),
file: ptr::null(),
line: 0,
color: 0,
},
_name: cname,
})),
};
cache.insert(name.to_string(), span);
span
}
#[inline(always)]
pub fn __enter(self) -> RunningZone {
if enabled() {
unsafe {
let zone = tracy_client_sys::___tracy_emit_zone_begin(&self.data.loc, 1);
RunningZone(Some(zone))
}
} else {
RunningZone(None)
}
}
}
macro_rules! create_zone_name {
($($tt:tt)*) => {
crate::tracy::ZoneName::__get(&format!($($tt)*))
};
}
pub struct RunningZone(Option<___tracy_c_zone_context>);
impl Drop for RunningZone {
#[inline(always)]
fn drop(&mut self) {
if let Some(zone) = self.0 {
unsafe {
___tracy_emit_zone_end(zone);
}
}
}
}
macro_rules! dynamic_raii_zone {
($name:expr) => {{
let name: ZoneName = $name;
name.__enter()
}};
}
macro_rules! dynamic_zone {
($name:expr) => {
let _zone = dynamic_raii_zone!($name);
};
}
macro_rules! raii_zone {
($($tt:tt)*) => {
{
static CACHE: std::sync::LazyLock<crate::tracy::ZoneName> = std::sync::LazyLock::new(|| {
create_zone_name!($($tt)*)
});
CACHE.__enter()
}
};
}
macro_rules! zone {
($($tt:tt)*) => {
let _zone = raii_zone!($($tt)*);
};
}
#[derive(Copy, Clone)]
pub struct FrameName {
name: &'static CString,
}
static FRAME_CACHE: LazyLock<Mutex<AHashMap<String, FrameName>>> =
LazyLock::new(|| Default::default());
impl FrameName {
pub fn get(name: &str) -> Self {
let mut cache = FRAME_CACHE.lock();
if let Some(frame_name) = cache.get(name) {
return *frame_name;
}
let cname = CString::new(name).unwrap();
let span = Self {
name: Box::leak(Box::new(cname)),
};
cache.insert(name.to_string(), span);
span
}
#[inline(always)]
pub fn __start(self) -> RenderingFrame {
if enabled() {
unsafe {
___tracy_emit_frame_mark_start(self.name.as_ptr());
}
}
RenderingFrame { name: self.name }
}
}
macro_rules! raii_frame {
($name:expr) => {{
let name: FrameName = $name;
name.__start()
}};
}
macro_rules! frame {
($name:expr) => {
let _frame = raii_frame!($name);
};
}
pub struct RenderingFrame {
name: &'static CString,
}
impl Drop for RenderingFrame {
#[inline(always)]
fn drop(&mut self) {
if enabled() {
unsafe {
___tracy_emit_frame_mark_end(self.name.as_ptr());
}
}
}
}
#[no_mangle]
#[allow(static_mut_refs)]
unsafe extern "C" fn ___tracy_demangle(
mangled: *const std::ffi::c_char,
) -> *const std::ffi::c_char {
use std::io::Write;
if mangled.is_null() {
return ptr::null();
}
let Ok(mangled) = CStr::from_ptr(mangled).to_str() else {
return ptr::null();
};
let demangled = rustc_demangle::demangle(mangled);
static mut BUF: Vec<u8> = Vec::new();
BUF.clear();
if let Err(_) = write!(BUF, "{demangled:#}\0") {
return ptr::null();
}
BUF.as_ptr().cast()
}
static ENABLED: AtomicBool = AtomicBool::new(false);
#[inline(always)]
fn enabled() -> bool {
ENABLED.load(Relaxed)
}
pub fn enable_profiler() {
unsafe {
___tracy_startup_profiler();
}
ENABLED.store(true, Relaxed);
}

51
src/tracy/tracy_noop.rs Normal file
View file

@ -0,0 +1,51 @@
#![allow(unused_macros)]
#[derive(Copy, Clone)]
pub struct ZoneName;
#[derive(Copy, Clone)]
pub struct FrameName;
impl FrameName {
pub fn get(_name: &str) -> Self {
Self
}
}
macro_rules! create_zone_name {
($($tt:tt)*) => {
crate::tracy::ZoneName
};
}
macro_rules! dynamic_raii_zone {
($name:expr) => {};
}
macro_rules! dynamic_zone {
($name:expr) => {};
}
macro_rules! raii_zone {
($($tt:tt)*) => {
()
};
}
macro_rules! zone {
($($tt:tt)*) => {};
}
macro_rules! raii_frame {
($name:expr) => {
()
};
}
macro_rules! frame {
($name:expr) => {};
}
pub fn enable_profiler() {
// nothing
}

View file

@ -19,7 +19,7 @@ impl RunToplevel {
let slf = Rc::new(RunToplevel { let slf = Rc::new(RunToplevel {
queue: Default::default(), queue: Default::default(),
}); });
let future = eng.spawn({ let future = eng.spawn("run toplevel", {
let slf = slf.clone(); let slf = slf.clone();
async move { async move {
loop { loop {

View file

@ -140,7 +140,7 @@ impl WaitForSyncObj {
trigger: Default::default(), trigger: Default::default(),
}); });
Waiter { Waiter {
_task: self.eng.spawn(waiter.clone().run()), _task: self.eng.spawn("wait for sync obj", waiter.clone().run()),
inner: waiter, inner: waiter,
} }
} }

View file

@ -128,7 +128,7 @@ impl Wheel {
cached_futures: Default::default(), cached_futures: Default::default(),
}); });
data.dispatcher data.dispatcher
.set(Some(eng.spawn(data.clone().dispatch()))); .set(Some(eng.spawn("wheel", data.clone().dispatch())));
Ok(Rc::new(Wheel { data })) Ok(Rc::new(Wheel { data }))
} }

View file

@ -146,6 +146,7 @@ impl UsrCon {
); );
slf.incoming.set(Some( slf.incoming.set(Some(
slf.eng.spawn( slf.eng.spawn(
"wl_usr incoming",
Incoming { Incoming {
con: slf.clone(), con: slf.clone(),
buf: BufFdIn::new(&socket, &slf.ring), buf: BufFdIn::new(&socket, &slf.ring),
@ -156,6 +157,7 @@ impl UsrCon {
)); ));
slf.outgoing.set(Some( slf.outgoing.set(Some(
slf.eng.spawn( slf.eng.spawn(
"wl_usr outgoing",
Outgoing { Outgoing {
con: slf.clone(), con: slf.clone(),
buf: BufFdOut::new(&socket, &slf.ring), buf: BufFdOut::new(&socket, &slf.ring),

View file

@ -453,9 +453,11 @@ impl Xcon {
xorg: CloneCell::new(Weak::new()), xorg: CloneCell::new(Weak::new()),
events: Default::default(), events: Default::default(),
}); });
let outgoing = state let outgoing = state.eng.spawn2(
.eng "xcon send",
.spawn2(Phase::PostLayout, handle_outgoing(data.clone())); Phase::PostLayout,
handle_outgoing(data.clone()),
);
let mut buf = data.bufio.buf(); let mut buf = data.bufio.buf();
let mut fds = vec![]; let mut fds = vec![];
{ {
@ -502,7 +504,9 @@ impl Xcon {
return Err(XconError::Authenticate(reason.to_owned())); return Err(XconError::Authenticate(reason.to_owned()));
} }
let setup = Setup::deserialize(&mut parser)?; let setup = Setup::deserialize(&mut parser)?;
let incoming = state.eng.spawn(handle_incoming(data.clone(), incoming)); let incoming = state
.eng
.spawn("X incoming", handle_incoming(data.clone(), incoming));
let slf = Rc::new(Self { let slf = Rc::new(Self {
extensions: data.fetch_extension_data().await?, extensions: data.fetch_extension_data().await?,
outgoing: Cell::new(Some(outgoing)), outgoing: Cell::new(Some(outgoing)),

View file

@ -150,7 +150,9 @@ async fn run(
Ok(w) => w, Ok(w) => w,
Err(e) => return Err(XWaylandError::Socketpair(e.into())), Err(e) => return Err(XWaylandError::Socketpair(e.into())),
}; };
let stderr_read = state.eng.spawn(log_xwayland(state.clone(), stderr_read)); let stderr_read = state
.eng
.spawn("log Xwayland", log_xwayland(state.clone(), stderr_read));
let pidfd = forker let pidfd = forker
.xwayland( .xwayland(
&state, &state,
@ -188,7 +190,7 @@ async fn run(
Ok(w) => w, Ok(w) => w,
Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))), Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))),
}; };
let _wm = state.eng.spawn(wm.run()); let _wm = state.eng.spawn("XWM", wm.run());
state.ring.readable(&pidfd).await?; state.ring.readable(&pidfd).await?;
} }
state.xwayland.queue.clear(); state.xwayland.queue.clear();

View file

@ -1678,7 +1678,7 @@ impl Wm {
}; };
self.shared self.shared
.transfers .transfers
.set(id, self.state.eng.spawn(wtx.run())); .set(id, self.state.eng.spawn("wayland to X transfer", wtx.run()));
} }
} }
} }
@ -1781,9 +1781,12 @@ impl Wm {
state: self.state.clone(), state: self.state.clone(),
shared: self.shared.clone(), shared: self.shared.clone(),
}; };
self.shared self.shared.transfers.set(
.transfers id,
.set(id, self.state.eng.spawn(transfer.run())); self.state
.eng
.spawn("X to wayland transfer", transfer.run()),
);
} }
} }