genode/ports/src/noux/local_rm_service.h

147 lines
3.8 KiB
C++

/*
* \brief RM service provided to Noux processes
* \author Norman Feske
* \date 2012-02-22
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _NOUX__LOCAL_RM_SERVICE_H_
#define _NOUX__LOCAL_RM_SERVICE_H_
/* Genode includes */
#include <base/service.h>
/* Noux includes */
#include <dataspace_registry.h>
#include <rm_session_component.h>
namespace Noux {
class Rm_dataspace_info : public Dataspace_info
{
private:
Rm_session_component * const _sub_rm;
Rpc_entrypoint &_ep;
Rm_session_capability _rm_cap;
public:
/**
* Constructor
*
* \param sub_rm pointer to 'Rm_session_component' that belongs
* to the 'Rm_dataspace_info' object
* \param ep entrypoint to manage the 'Rm_session_component'
*
* The ownership of the pointed-to object gets transferred to the
* 'Rm_dataspace_info' object. I.e., 'sub_rm' will get destructed
* on the destruction of its corresponding 'Rm_dataspace_info'
* object. Also, 'Rm_dataspace_info' takes care of associating
* 'sub_rm' with 'ep'.
*/
Rm_dataspace_info(Rm_session_component *sub_rm,
Rpc_entrypoint &ep)
:
Dataspace_info(sub_rm->dataspace()),
_sub_rm(sub_rm), _ep(ep), _rm_cap(_ep.manage(_sub_rm))
{ }
~Rm_dataspace_info()
{
_ep.dissolve(_sub_rm);
destroy(env()->heap(), _sub_rm);
}
Rm_session_capability rm_cap() { return _rm_cap; }
Dataspace_capability fork(Ram_session_capability ram,
Dataspace_registry &ds_registry,
Rpc_entrypoint &ep)
{
Rm_session_component *new_sub_rm =
new Rm_session_component(ds_registry, 0, size());
Rm_dataspace_info *rm_info = new Rm_dataspace_info(new_sub_rm, ep);
_sub_rm->replay(ram, rm_info->rm_cap(), ds_registry, ep);
ds_registry.insert(rm_info);
return new_sub_rm->dataspace();
}
void poke(addr_t dst_offset, void const *src, size_t len)
{
if ((dst_offset >= size()) || (dst_offset + len > size())) {
PERR("illegal attemt to write beyond RM boundary");
return;
}
_sub_rm->poke(dst_offset, src, len);
}
};
class Local_rm_service : public Service
{
private:
Rpc_entrypoint &_ep;
Dataspace_registry &_ds_registry;
public:
Local_rm_service(Rpc_entrypoint &ep, Dataspace_registry &ds_registry)
:
Service(Rm_session::service_name()), _ep(ep),
_ds_registry(ds_registry)
{ }
Genode::Session_capability session(const char *args, Affinity const &)
{
addr_t start = Arg_string::find_arg(args, "start").ulong_value(~0UL);
size_t size = Arg_string::find_arg(args, "size").ulong_value(0);
Rm_session_component *rm =
new Rm_session_component(_ds_registry, start, size);
Rm_dataspace_info *info = new Rm_dataspace_info(rm, _ep);
_ds_registry.insert(info);
return info->rm_cap();
}
void upgrade(Genode::Session_capability, const char *args) { }
void close(Genode::Session_capability session)
{
Object_pool<Rm_session_component>::Guard
rm_session(_ep.lookup_and_lock(session));
if (!rm_session) {
PWRN("Unexpected call of close with non-RM-session argument");
return;
}
/* use RM dataspace as key to obtain the dataspace info object */
Dataspace_capability ds_cap = rm_session->dataspace();
/* release dataspace info */
Dataspace_info *info = _ds_registry.lookup_info(ds_cap);
if (info) {
info->dissolve_users();
_ds_registry.remove(info);
destroy(env()->heap(), info);
} else {
PWRN("Could not lookup dataspace info for local RM session");
}
}
};
}
#endif /* _NOUX__LOCAL_RM_SERVICE_H_ */