mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-09 04:15:52 +00:00
base: fix deadlock in core_env on base-nova
During a ram_session->free call in 'core' the lock in core_env.h is taken. Then in the ram_session::_free_ds implementation the dissolve function for the dataspace is called. base-nova tries to make sure that the ds is not accessible anymore by any kind of parallel incoming IPC by performing a cleanup IPC. Unfortunately the dataspace_session implementation uses the very same allocator in 'core' and may require to obtain the same lock as taken in ram_session->free. This leads to a spurious deadlock on base-nova. The actual free_ds implementation is mostly thread safe, since all used objects inside there are already locked. The only missing piece is the _payload variable. By changing the _payload variable in a atomic fashion there is no need to lock the whole ram_session->free call which avoids deadlocks on base-nova. Fixes #549
This commit is contained in:
parent
edd30b56a2
commit
7868156b19
@ -77,7 +77,6 @@ namespace Genode {
|
||||
|
||||
void free(Ram_dataspace_capability ds)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
RAM_SESSION_IMPL::free(ds);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <base/tslab.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/sync_allocator.h>
|
||||
|
||||
/* core includes */
|
||||
#include <dataspace_component.h>
|
||||
@ -38,7 +39,7 @@ namespace Genode {
|
||||
|
||||
enum { SBS = 1024 }; /* slab block size */
|
||||
|
||||
typedef Tslab<Dataspace_component, SBS> Ds_slab;
|
||||
typedef Synchronized_allocator<Tslab<Dataspace_component, SBS> > Ds_slab;
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Rpc_entrypoint *_ram_session_ep;
|
||||
|
@ -39,12 +39,12 @@ void Ram_session_component::_free_ds(Dataspace_component *ds)
|
||||
|
||||
size_t ds_size = ds->size();
|
||||
|
||||
/* destroy native shared memory representation */
|
||||
_revoke_ram_ds(ds);
|
||||
|
||||
/* tell entry point to forget the dataspace */
|
||||
_ds_ep->dissolve(ds);
|
||||
|
||||
/* destroy native shared memory representation */
|
||||
_revoke_ram_ds(ds);
|
||||
|
||||
/* XXX: remove dataspace from all RM sessions */
|
||||
|
||||
/* free physical memory that was backing the dataspace */
|
||||
@ -54,6 +54,7 @@ void Ram_session_component::_free_ds(Dataspace_component *ds)
|
||||
destroy(&_ds_slab, ds);
|
||||
|
||||
/* adjust payload */
|
||||
Lock::Guard lock_guard(_ref_members_lock);
|
||||
_payload -= ds_size;
|
||||
}
|
||||
|
||||
@ -181,9 +182,6 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, bool cache
|
||||
*/
|
||||
_clear_ds(ds);
|
||||
|
||||
/* keep track of the used quota for actual payload */
|
||||
_payload += ds_size;
|
||||
|
||||
if (verbose)
|
||||
PDBG("ds_size=%zd, used_quota=%zd quota_limit=%zd",
|
||||
ds_size, used_quota(), _quota_limit);
|
||||
@ -193,6 +191,10 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, bool cache
|
||||
/* create native shared memory representation of dataspace */
|
||||
_export_ram_ds(ds);
|
||||
|
||||
Lock::Guard lock_guard(_ref_members_lock);
|
||||
/* keep track of the used quota for actual payload */
|
||||
_payload += ds_size;
|
||||
|
||||
return static_cap_cast<Ram_dataspace>(result);
|
||||
}
|
||||
|
||||
@ -258,7 +260,7 @@ Ram_session_component::Ram_session_component(Rpc_entrypoint *ds_ep,
|
||||
Ram_session_component::~Ram_session_component()
|
||||
{
|
||||
/* destroy all dataspaces */
|
||||
for (Dataspace_component *ds; (ds = _ds_slab.first_object()); _free_ds(ds));
|
||||
for (Dataspace_component *ds; (ds = _ds_slab.raw()->first_object()); _free_ds(ds));
|
||||
|
||||
if (_payload != 0)
|
||||
PWRN("Remaining payload of %zd in ram session to destroy", _payload);
|
||||
|
Loading…
x
Reference in New Issue
Block a user