diff --git a/base/src/core/include/rm_session_component.h b/base/src/core/include/rm_session_component.h index e24f7aa7a0..5e6df370b4 100644 --- a/base/src/core/include/rm_session_component.h +++ b/base/src/core/include/rm_session_component.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -258,8 +259,9 @@ namespace Genode { }; - Tslab _client_slab; /* backing store for - client structures */ + typedef Synchronized_allocator > Client_slab_alloc; + Client_slab_alloc _client_slab; /* backing store for + client structures, synchronized */ Tslab _ref_slab; /* backing store for region list */ Allocator_avl_tpl _map; /* region map for attach, diff --git a/base/src/core/rm_session_component.cc b/base/src/core/rm_session_component.cc index 340dd87eaa..d86c43ac66 100644 --- a/base/src/core/rm_session_component.cc +++ b/base/src/core/rm_session_component.cc @@ -683,9 +683,28 @@ Rm_session::State Rm_session_component::state() void Rm_session_component::dissolve(Rm_client *cl) { - Lock::Guard lock_guard(_lock); - _pager_ep->dissolve(cl); - _clients.remove(cl); + { + Lock::Guard lock_guard(_lock); + _pager_ep->dissolve(cl); + _clients.remove(cl); + } + + /* + * Rm_client is derived from Pager_object. If the Pager_object is also + * derived from Thread_base then the Rm_client object must be + * destructed without holding the rm_session_object lock. The native + * platform specific Thread_base implementation has to take care that + * all in-flight page handling requests are finished before + * destruction. (Either by waiting until the end of or by + * cancellation of the last in-flight request. + * This operation can also require taking the rm_session_object lock. + * + * Since _client_slab insertion/deletion also must be performed + * synchronized but can't be protected by the rm_session_object lock + * because of the described potential dead_lock situation, we have + * to use a synchronized allocator object to perform insertion and + * deletion of Rm_clients. + */ destroy(&_client_slab, cl); } @@ -728,13 +747,11 @@ Rm_session_component::~Rm_session_component() } /* remove all clients */ - while (Rm_client *cl = _client_slab.first_object()) { - _pager_ep->dissolve(cl); + while (Rm_client *cl = _client_slab.raw()->first_object()) { _lock.unlock(); cl->dissolve_from_faulting_rm_session(); + this->dissolve(cl); _lock.lock(); - _clients.remove(cl); - destroy(&_client_slab, cl); } /* detach all regions */