From 30ddd43e6da80effba4b0061dc9a8196f9a7068f Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 14 May 2024 12:38:14 +0200 Subject: [PATCH] event: break long dependency chains on drop This prevents stack overflows on drop without making it expensive to read from dependencies (e.g. my attempt to use Weak instead). Cc: mesa-stable Part-of: (cherry picked from commit 48c752d3e060fc62dcc5ed228c2464efc6591029) --- .pick_status.json | 2 +- src/gallium/frontends/rusticl/core/event.rs | 22 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.pick_status.json b/.pick_status.json index 580b517933b..725cb9dff59 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -2264,7 +2264,7 @@ "description": "event: break long dependency chains on drop", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/gallium/frontends/rusticl/core/event.rs b/src/gallium/frontends/rusticl/core/event.rs index 6389d6de831..bc0849aab93 100644 --- a/src/gallium/frontends/rusticl/core/event.rs +++ b/src/gallium/frontends/rusticl/core/event.rs @@ -10,6 +10,7 @@ use mesa_rust_util::static_assert; use rusticl_opencl_gen::*; use std::collections::HashSet; +use std::mem; use std::slice; use std::sync::Arc; use std::sync::Condvar; @@ -272,6 +273,27 @@ impl Event { } } +impl Drop for Event { + // implement drop in order to prevent stack overflows of long dependency chains. + // + // This abuses the fact that `Arc::into_inner` only succeeds when there is one strong reference + // so we turn a recursive drop chain into a drop list for events having no other references. + fn drop(&mut self) { + if self.deps.is_empty() { + return; + } + + let mut deps_list = vec![mem::take(&mut self.deps)]; + while let Some(deps) = deps_list.pop() { + for dep in deps { + if let Some(mut dep) = Arc::into_inner(dep) { + deps_list.push(mem::take(&mut dep.deps)); + } + } + } + } +} + // TODO worker thread per device // Condvar to wait on new events to work on // notify condvar when flushing queue events to worker