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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29190>
(cherry picked from commit 48c752d3e0)
This commit is contained in:
Karol Herbst 2024-05-14 12:38:14 +02:00 committed by Eric Engestrom
parent 7f095e142b
commit cbb030e829
2 changed files with 23 additions and 1 deletions

View file

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

View file

@ -10,6 +10,7 @@ use mesa_rust_util::static_assert;
use rusticl_opencl_gen::*;
use std::collections::HashSet;
use std::mem;
use std::sync::Arc;
use std::sync::Condvar;
use std::sync::Mutex;
@ -262,6 +263,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