mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-01 15:10:56 +00:00
Deadlock fix in rm_session on NOVA platform
Rm_client is derived from Pager_object. If the Pager_object is also derived from Thread_base (which is the case for NOVA) 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. On NOVA it is done by doing an IPC to the pager thread. (performed in Pager_object::dissolve() in base-nova). The called thread than executes its operation until end which also requires in some cases to take 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 dead_lock situation, we have to use a synchronized allocator object to perform insertion and deletion of Rm_clients.
This commit is contained in:
parent
8ee4442108
commit
4ece3b3c77
@ -22,6 +22,7 @@
|
|||||||
#include <base/pager.h>
|
#include <base/pager.h>
|
||||||
#include <base/allocator_avl.h>
|
#include <base/allocator_avl.h>
|
||||||
#include <base/allocator_guard.h>
|
#include <base/allocator_guard.h>
|
||||||
|
#include <base/sync_allocator.h>
|
||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
@ -258,8 +259,9 @@ namespace Genode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Tslab<Rm_client, 1024> _client_slab; /* backing store for
|
typedef Synchronized_allocator<Tslab<Rm_client, 1024> > Client_slab_alloc;
|
||||||
client structures */
|
Client_slab_alloc _client_slab; /* backing store for
|
||||||
|
client structures, synchronized */
|
||||||
Tslab<Rm_region_ref, 1024> _ref_slab; /* backing store for
|
Tslab<Rm_region_ref, 1024> _ref_slab; /* backing store for
|
||||||
region list */
|
region list */
|
||||||
Allocator_avl_tpl<Rm_region> _map; /* region map for attach,
|
Allocator_avl_tpl<Rm_region> _map; /* region map for attach,
|
||||||
|
@ -683,9 +683,28 @@ Rm_session::State Rm_session_component::state()
|
|||||||
|
|
||||||
void Rm_session_component::dissolve(Rm_client *cl)
|
void Rm_session_component::dissolve(Rm_client *cl)
|
||||||
{
|
{
|
||||||
Lock::Guard lock_guard(_lock);
|
{
|
||||||
_pager_ep->dissolve(cl);
|
Lock::Guard lock_guard(_lock);
|
||||||
_clients.remove(cl);
|
_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
|
||||||
|
* <deadlock free> 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);
|
destroy(&_client_slab, cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,13 +747,11 @@ Rm_session_component::~Rm_session_component()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* remove all clients */
|
/* remove all clients */
|
||||||
while (Rm_client *cl = _client_slab.first_object()) {
|
while (Rm_client *cl = _client_slab.raw()->first_object()) {
|
||||||
_pager_ep->dissolve(cl);
|
|
||||||
_lock.unlock();
|
_lock.unlock();
|
||||||
cl->dissolve_from_faulting_rm_session();
|
cl->dissolve_from_faulting_rm_session();
|
||||||
|
this->dissolve(cl);
|
||||||
_lock.lock();
|
_lock.lock();
|
||||||
_clients.remove(cl);
|
|
||||||
destroy(&_client_slab, cl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detach all regions */
|
/* detach all regions */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user