From cd4d00f31a0733f2749291043c120138fb56326c Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Thu, 20 Jan 2022 14:15:07 +0100 Subject: [PATCH] gpu/intel: remove deadlock during session destruction * use 'Id_space::apply_any' instead of 'for_each' to destroy session local buffer objects * save session capability in session because 'cap()' is not valid in 'Session_component' destructor because it was dissolved before calling 'Root::_destruct_session', the cap is necessary to remove owned buffers from the EP issue #4380 --- repos/os/src/drivers/gpu/intel/main.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index cbe8c65dc7..231cfdb2f6 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -1480,6 +1480,7 @@ class Gpu::Session_component : public Genode::Session_object Genode::Region_map &_rm; Constrained_ram_allocator _ram; Heap _heap { _ram, _rm }; + Capability _session_cap { cap() }; Igd::Device &_device; Igd::Device::Vgpu _vgpu; @@ -1695,7 +1696,7 @@ class Gpu::Session_component : public Genode::Session_object _apply_buffer(buffer_local, [&](Buffer &buffer) { - if (buffer.owner(cap()) == false) return false; + if (buffer.owner(_session_cap) == false) return false; if (buffer.map.offset != Igd::Ggtt::Mapping::INVALID_OFFSET) { _device.unmap_buffer(_heap, buffer.map); @@ -1716,7 +1717,8 @@ class Gpu::Session_component : public Genode::Session_object _free_local_buffer(buffer_local); }; - _buffer_space.for_each(lookup_and_free); + while(_buffer_space.apply_any( + [&] (Buffer_local &buffer_local) { lookup_and_free(buffer_local); })); } /********************************* @@ -1810,7 +1812,7 @@ class Gpu::Session_component : public Genode::Session_object Genode::Dataspace_capability ds_cap = _device.alloc_buffer(_heap, size); - Buffer *buffer = new (&_heap) Buffer(ds_cap, cap()); + Buffer *buffer = new (&_heap) Buffer(ds_cap, _session_cap); _env.ep().manage(*buffer); try { new (&_heap) Buffer_local(buffer->cap(), size, _buffer_space, id); @@ -1843,7 +1845,7 @@ class Gpu::Session_component : public Genode::Session_object _apply_buffer(buffer_local, [&](Buffer &buffer) { - if (buffer.owner(cap()) == false) return false; + if (buffer.owner(_session_cap) == false) return false; if (buffer.map.offset != Igd::Ggtt::Mapping::INVALID_OFFSET) { Genode::error("cannot free mapped buffer"); @@ -1904,7 +1906,7 @@ class Gpu::Session_component : public Genode::Session_object Genode::Dataspace_capability map_cap; auto lookup_and_map = [&] (Buffer &buffer) { - if (buffer.owner(cap()) == false) { + if (buffer.owner(_session_cap) == false) { Genode::error("GGTT mappings can only be done by buffer owner"); return false; } @@ -1947,7 +1949,7 @@ class Gpu::Session_component : public Genode::Session_object auto lookup_and_unmap = [&] (Buffer &buffer) { - if (buffer.owner(cap()) == false) { + if (buffer.owner(_session_cap) == false) { Genode::error("GGTT unmappings can only be done by buffer owner"); return false; } @@ -2071,7 +2073,7 @@ class Gpu::Session_component : public Genode::Session_object Buffer *b = nullptr; auto lookup = [&] (Buffer &buffer) { - if (!buffer.map.cap.valid() || !buffer.owner(cap())) { return false; } + if (!buffer.map.cap.valid() || !buffer.owner(_session_cap)) { return false; } b = &buffer; return false; };