Loading...
Searching...
No Matches
object_registry
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include <l4/re/util/cap_alloc>
#include <l4/re/util/unique_cap>
#include <l4/re/consts>
#include <l4/re/env>
#include <l4/sys/cxx/ipc_server_loop>
#include <l4/sys/factory>
#include <l4/sys/task>
#include <l4/sys/thread>
#include <l4/sys/ipc_gate>
#include <l4/cxx/exceptions>
namespace L4Re { namespace Util {
class Object_registry :
public L4::Basic_registry,
public L4::Registry_iface
{
struct Null_handler : L4::Epiface_t<Null_handler, L4::Kobject>
{};
protected:
L4::Cap<L4::Thread> _server;
L4::Cap<L4::Factory> _factory;
L4::Ipc_svr::Server_iface *_sif;
private:
Null_handler _null_handler;
public:
explicit
Object_registry(L4::Ipc_svr::Server_iface *sif)
: _server(L4Re::Env::env()->main_thread()),
_factory(L4Re::Env::env()->factory()),
_sif(sif)
{}
Object_registry(L4::Ipc_svr::Server_iface *sif,
L4::Cap<L4::Thread> server,
L4::Cap<L4::Factory> factory)
: _server(server), _factory(factory), _sif(sif)
{}
private:
typedef L4::Ipc_svr::Server_iface Server_iface;
typedef Server_iface::Demand Demand;
L4::Cap<L4::Rcv_endpoint>
_register_ep(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep,
Demand const &demand)
{
int err = _sif->alloc_buffer_demand(demand);
if (err < 0)
return L4::Cap<L4::Rcv_endpoint>(err | L4_INVALID_CAP_BIT);
err = o->set_server(_sif, ep);
if (err < 0)
return L4::Cap<L4::Rcv_endpoint>(err | L4_INVALID_CAP_BIT);
l4_umword_t id = l4_umword_t(o);
err = l4_error(ep->bind_thread(_server, id));
if (err < 0)
return L4::Cap<L4::Rcv_endpoint>(err | L4_INVALID_CAP_BIT);
return ep;
}
L4::Cap<void> _register_ep(L4::Epiface *o, char const *service,
Demand const &demand)
{
L4::Cap<L4::Rcv_endpoint> cap = L4Re::Env::env()->get_cap<L4::Rcv_endpoint>(service);
if (!cap.is_valid())
return cap;
return _register_ep(o, cap, demand);
}
L4::Cap<void> _register_gate(L4::Epiface *o, Demand const &demand)
{
int err = _sif->alloc_buffer_demand(demand);
if (err < 0)
return L4::Cap<void>(err | L4_INVALID_CAP_BIT);
auto cap = L4Re::Util::make_unique_cap<L4::Kobject>();
if (!cap.is_valid())
return cap.get();
l4_umword_t id = l4_umword_t(o);
err = l4_error(_factory->create_gate(cap.get(), _server, id));
if (err < 0)
return L4::Cap<void>(err | L4_INVALID_CAP_BIT);
err = o->set_server(_sif, cap.get(), true);
if (err < 0)
return L4::Cap<void>(err | L4_INVALID_CAP_BIT);
return cap.release();
}
L4::Cap<L4::Irq> _register_irq(L4::Epiface *o,
Demand const &demand)
{
int err = _sif->alloc_buffer_demand(demand);
if (err < 0)
return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
auto cap = L4Re::Util::make_unique_cap<L4::Irq>();
if (!cap.is_valid())
return cap.get();
l4_umword_t id = l4_umword_t(o);
err = l4_error(_factory->create(cap.get()));
if (err < 0)
return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
err = o->set_server(_sif, cap.get(), true);
if (err < 0)
return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
err = l4_error(cap->bind_thread(_server, id));
if (err < 0)
return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
return cap.release();
}
static Demand _get_buffer_demand(L4::Epiface *o)
{ return o->get_buffer_demand(); }
template<typename T>
static Demand _get_buffer_demand(T *,
typename L4::Kobject_typeid<typename T::Interface>::Demand
d = typename L4::Kobject_typeid<typename T::Interface>::Demand())
{ return d; }
public:
L4::Cap<void> register_obj(L4::Epiface *o, char const *service) override
{
return _register_ep(o, service, _get_buffer_demand(o));
}
L4::Cap<void> register_obj(L4::Epiface *o) override
{
return _register_gate(o, _get_buffer_demand(o));
}
L4::Cap<L4::Irq> register_irq_obj(L4::Epiface *o) override
{
return _register_irq(o, _get_buffer_demand(o));
}
L4::Cap<L4::Rcv_endpoint>
register_obj(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep) override
{
return _register_ep(o, ep, _get_buffer_demand(o));
}
void unregister_obj(L4::Epiface *o, bool unmap = true) override
{
L4::Epiface::Stored_cap c;
if (!o || !o->obj_cap().is_valid())
return;
c = o->obj_cap();
if (unmap)
L4::Cap<L4::Task>(L4Re::This_task)->unmap(c.fpage(), L4_FP_ALL_SPACES);
// make sure unhandled ipc ends up with the null handler
L4::Thread::Modify_senders todo;
todo.add(~3UL, reinterpret_cast< l4_umword_t >(o),
~0UL, reinterpret_cast< l4_umword_t >
(static_cast< L4::Epiface *>(&_null_handler)));
_server->modify_senders(todo);
// we use bit 4 to indicated an internally allocated cap
if (c.managed())
cap_alloc.free(c);
o->set_server(0, L4::Cap<void>::Invalid);
}
};
template< typename LOOP_HOOKS = L4::Ipc_svr::Default_loop_hooks >
class Registry_server : public L4::Server<LOOP_HOOKS>
{
private:
typedef L4::Server<LOOP_HOOKS> Base;
Object_registry _registry;
public:
Registry_server() : _registry(this)
{}
Registry_server(l4_utcb_t *, L4::Cap<L4::Thread> server,
L4::Cap<L4::Factory> factory) L4_DEPRECATED("Omit UTCB pointer argument")
: _registry(this, server, factory)
{}
Registry_server(L4::Cap<L4::Thread> server,
L4::Cap<L4::Factory> factory)
: _registry(this, server, factory)
{}
Object_registry const *registry() const { return &_registry; }
Object_registry *registry() { return &_registry; }
void L4_NORETURN loop(l4_utcb_t *utcb = l4_utcb())
{ Base::template loop<L4::Runtime_error, Object_registry &>(_registry, utcb); }
template <typename Printer>
void L4_NORETURN loop_dbg(Printer printer, l4_utcb_t *utcb = l4_utcb())
{
Base::template loop_dbg<L4::Runtime_error, Object_registry &, Printer>
(_registry, printer, utcb);
}
};
}}
L4Re::Env
C++ interface of the initial environment that is provided to an L4 task.
Definition env:79
L4Re::Env::env
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:96
L4Re::Env::get_cap
L4::Cap< T > get_cap(char const *name, unsigned l) const noexcept
Get the capability selector for the object named name.
Definition env:197
L4Re::Util::Object_registry
A registry that manages server objects and their attached IPC gates for a single server loop for a sp...
Definition object_registry:44
L4Re::Util::Object_registry::register_obj
L4::Cap< L4::Rcv_endpoint > register_obj(L4::Epiface *o, L4::Cap< L4::Rcv_endpoint > ep) override
Register a handler for an already existing interrupt.
Definition object_registry:246
L4Re::Util::Object_registry::register_irq_obj
L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o) override
Register a handler for an interrupt.
Definition object_registry:227
L4Re::Util::Object_registry::register_obj
L4::Cap< void > register_obj(L4::Epiface *o, char const *service) override
Register a new server object to a pre-allocated receive endpoint.
Definition object_registry:194
L4Re::Util::Object_registry::register_obj
L4::Cap< void > register_obj(L4::Epiface *o) override
Register a new server object on a newly allocated capability.
Definition object_registry:211
L4Re::Util::Object_registry::Object_registry
Object_registry(L4::Ipc_svr::Server_iface *sif, L4::Cap< L4::Thread > server, L4::Cap< L4::Factory > factory)
Create a registry for arbitrary threads.
Definition object_registry:81
L4Re::Util::Object_registry::Object_registry
Object_registry(L4::Ipc_svr::Server_iface *sif)
Create a registry for the main thread of the task using the default factory.
Definition object_registry:67
L4Re::Util::Object_registry::unregister_obj
void unregister_obj(L4::Epiface *o, bool unmap=true) override
Remove a server object from the handler list.
Definition object_registry:262
L4Re::Util::Registry_server::registry
Object_registry const * registry() const
Return registry of this server loop.
Definition object_registry:334
L4Re::Util::Registry_server::loop
void L4_NORETURN loop(l4_utcb_t *utcb=l4_utcb())
Start the server loop.
Definition object_registry:344
L4Re::Util::Registry_server::Registry_server
Registry_server(L4::Cap< L4::Thread > server, L4::Cap< L4::Factory > factory)
Create a new server loop object for an arbitrary thread and factory.
Definition object_registry:328
L4Re::Util::Registry_server::Registry_server
Registry_server(l4_utcb_t *, L4::Cap< L4::Thread > server, L4::Cap< L4::Factory > factory)
Create a new server loop object for an arbitrary thread and factory.
Definition object_registry:317
L4Re::Util::Registry_server::Registry_server
Registry_server()
Create a new server loop object for the main thread of the task.
Definition object_registry:305
L4Re::Util::Registry_server::registry
Object_registry * registry()
Return registry of this server loop.
Definition object_registry:336
L4Re::Util::Registry_server::loop_dbg
void L4_NORETURN loop_dbg(Printer printer, l4_utcb_t *utcb=l4_utcb())
Start the server loop with error printing.
Definition object_registry:356
L4::Basic_registry
This registry returns the corresponding server object based on the label of an Ipc_gate.
Definition ipc_epiface:530
L4::Cap_base::fpage
l4_fpage_t fpage(unsigned rights=L4_CAP_FPAGE_RWS) const noexcept
Return flexpage for the capability.
Definition capability.h:74
L4::Cap_base::is_valid
bool is_valid() const noexcept
Test whether the capability is a valid capability index (i.e., not L4_INVALID_CAP).
Definition capability.h:57
L4::Cap_base::Invalid
@ Invalid
Invalid capability selector.
Definition capability.h:42
L4::Cap
C++ interface for capabilities.
Definition capability.h:224
L4::Ipc_svr::Server_iface
Interface for server-loop related functions.
Definition ipc_epiface:37
L4::Ipc_svr::Server_iface::Demand
L4::Type_info::Demand Demand
Data type expressing server-side demand for receive buffers.
Definition ipc_epiface:44
L4::Ipc_svr::Server_iface::alloc_buffer_demand
virtual int alloc_buffer_demand(Demand const &demand)=0
Tells the server to allocate buffers for the given demand.
L4::Rcv_endpoint
Interface for kernel objects that allow to receive IPC from them.
Definition rcv_endpoint:33
L4::Registry_iface
Abstract interface for object registries.
Definition ipc_epiface:323
L4::Server
Basic server loop for handling client requests.
Definition ipc_server_loop:309
L4::Thread::Modify_senders
Class wrapping a list of rules which modify the sender label of IPC messages inbound to this thread.
Definition thread:449
L4::Thread::Modify_senders::add
int add(l4_umword_t match_mask, l4_umword_t match, l4_umword_t del_bits, l4_umword_t add_bits) noexcept
Add a rule.
Definition thread:481
env
Environment interface.
exceptions
Base exceptions.
factory
Common factory related definitions.
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_error
long l4_error(l4_msgtag_t tag) L4_NOTHROW
Get IPC error code if any or message tag label otherwise for an IPC call.
Definition ipc.h:646
L4_FP_ALL_SPACES
@ L4_FP_ALL_SPACES
Flag to tell the unmap operation to revoke permissions from all child mappings including the mapping ...
Definition consts.h:183
l4_utcb_t
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition utcb.h:56
l4_utcb
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
Definition utcb.h:346
L4Re::Util::cap_alloc
_Cap_alloc & cap_alloc
Capability allocator.
L4_NORETURN
#define L4_NORETURN
Noreturn function attribute.
Definition compiler.h:201
L4_DEPRECATED
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition compiler.h:289
ipc_gate
The C++ IPC gate interface.
L4Re::Util
Documentation of the L4 Runtime Environment utility functionality in C++.
Definition l4re.dox:21
L4Re::Util::make_unique_cap
Unique_cap< T > make_unique_cap()
Allocate a capability slot and wrap it in an Unique_cap.
Definition unique_cap:55
L4Re
L4Re C++ Interfaces.
Definition cmd_control:14
consts
Constants.
L4::Epiface_t
Epiface implementation for Kobject-based interface implementations.
Definition ipc_epiface:504
L4::Epiface
Base class for interface implementations.
Definition ipc_epiface:146
L4::Epiface::obj_cap
Stored_cap obj_cap() const
Get the capability to the kernel object belonging to this object.
Definition ipc_epiface:206
L4::Epiface::get_buffer_demand
virtual Demand get_buffer_demand() const =0
Get the server-side receive buffer demand for this object.
L4::Epiface::set_server
int set_server(Server_iface *srv, Cap< void > cap, bool managed=false)
Set server registration info for the object.
Definition ipc_epiface:224
L4::Kobject_typeid::Demand
T::__Kobject_typeid::Demand Demand
Data type expressing the static demand of receive buffers in a server.
Definition __typeinfo.h:622
thread
Common thread related definitions.
task
Common task related definitions.
cap_alloc
Capability allocator.
unique_cap
Unique_cap / Unique_del_cap.