L4Re – L4 Runtime Environment
object_registry
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  * Alexander Warg <warg@os.inf.tu-dresden.de>
5  * economic rights: Technische Universität Dresden (Germany)
6  *
7  * This file is part of TUD:OS and distributed under the terms of the
8  * GNU General Public License 2.
9  * Please see the COPYING-GPL-2 file for details.
10  *
11  * As a special exception, you may use this file as part of a free software
12  * library without restriction. Specifically, if other files instantiate
13  * templates or use macros or inline functions from this file, or you compile
14  * this file and link it with other files to produce an executable, this
15  * file does not by itself cause the resulting executable to be covered by
16  * the GNU General Public License. This exception does not however
17  * invalidate any other reasons why the executable file might be covered by
18  * the GNU General Public License.
19  */
20 
21 #pragma once
22 
23 #include <l4/re/util/cap_alloc>
24 #include <l4/re/util/unique_cap>
25 #include <l4/re/consts>
26 #include <l4/re/env>
27 
28 #include <l4/sys/cxx/ipc_server_loop>
29 #include <l4/sys/factory>
30 #include <l4/sys/task>
31 #include <l4/sys/thread>
32 #include <l4/sys/ipc_gate>
33 
34 #include <l4/cxx/exceptions>
35 
36 namespace L4Re { namespace Util {
37 
53  public L4::Basic_registry,
54  public L4::Registry_iface
55 {
60  struct Null_handler : L4::Epiface_t<Null_handler, L4::Kobject>
61  {};
62 
63 protected:
64  L4::Cap<L4::Thread> _server;
65  L4::Cap<L4::Factory> _factory;
67 
68 private:
69  Null_handler _null_handler;
70 
71 public:
77  explicit
79  : _server(L4Re::Env::env()->main_thread()),
80  _factory(L4Re::Env::env()->factory()),
81  _sif(sif)
82  {}
83 
93  L4::Cap<L4::Thread> server,
94  L4::Cap<L4::Factory> factory)
95  : _server(server), _factory(factory), _sif(sif)
96  {}
97 
98 private:
99  typedef L4::Ipc_svr::Server_iface Server_iface;
100  typedef Server_iface::Demand Demand;
101 
103  _register_ep(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep,
104  Demand const &demand)
105  {
106  int err = _sif->alloc_buffer_demand(demand);
107  if (err < 0)
108  return L4::Cap<L4::Rcv_endpoint>(err | L4_INVALID_CAP_BIT);
109 
110  l4_umword_t id = l4_umword_t(o);
111  err = l4_error(ep->bind_thread(_server, id));
112  if (err < 0)
113  return L4::Cap<L4::Rcv_endpoint>(err | L4_INVALID_CAP_BIT);
114 
115  err = o->set_server(_sif, ep);
116  if (err < 0)
117  return L4::Cap<L4::Rcv_endpoint>(err | L4_INVALID_CAP_BIT);
118 
119  return ep;
120  }
121 
122  L4::Cap<void> _register_ep(L4::Epiface *o, char const *service,
123  Demand const &demand)
124  {
126  if (!cap.is_valid())
127  return cap;
128 
129  return _register_ep(o, cap, demand);
130  }
131 
132  L4::Cap<void> _register_gate(L4::Epiface *o, Demand const &demand)
133  {
134  int err = _sif->alloc_buffer_demand(demand);
135  if (err < 0)
136  return L4::Cap<void>(err | L4_INVALID_CAP_BIT);
137 
138  auto cap = L4Re::Util::make_unique_cap<L4::Kobject>();
139 
140  if (!cap.is_valid())
141  return cap.get();
142 
143  l4_umword_t id = l4_umword_t(o);
144  err = l4_error(_factory->create_gate(cap.get(), _server, id));
145  if (err < 0)
146  return L4::Cap<void>(err | L4_INVALID_CAP_BIT);
147 
148  err = o->set_server(_sif, cap.get(), true);
149  if (err < 0)
150  return L4::Cap<void>(err | L4_INVALID_CAP_BIT);
151 
152  return cap.release();
153  }
154 
155  L4::Cap<L4::Irq> _register_irq(L4::Epiface *o,
156  Demand const &demand)
157  {
158  int err = _sif->alloc_buffer_demand(demand);
159  if (err < 0)
160  return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
161 
162  auto cap = L4Re::Util::make_unique_cap<L4::Irq>();
163 
164  if (!cap.is_valid())
165  return cap.get();
166 
167  l4_umword_t id = l4_umword_t(o);
168  err = l4_error(_factory->create(cap.get()));
169  if (err < 0)
170  return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
171 
172  err = l4_error(cap->bind_thread(_server, id));
173  if (err < 0)
174  return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
175 
176  err = o->set_server(_sif, cap.get(), true);
177  if (err < 0)
178  return L4::Cap<L4::Irq>(err | L4_INVALID_CAP_BIT);
179 
180  return cap.release();
181  }
182 
183  static Demand _get_buffer_demand(L4::Epiface *o)
184  { return o->get_buffer_demand(); }
185 
186  template<typename T>
187  static Demand _get_buffer_demand(T *,
190  { return d; }
191 
192 public:
205  L4::Cap<void> register_obj(L4::Epiface *o, char const *service) override
206  {
207  return _register_ep(o, service, _get_buffer_demand(o));
208  }
209 
223  {
224  return _register_gate(o, _get_buffer_demand(o));
225  }
226 
239  {
240  return _register_irq(o, _get_buffer_demand(o));
241  }
242 
243  // pass access to deprecated register_irq_obj
245 
261  {
262  return _register_ep(o, ep, _get_buffer_demand(o));
263  }
264 
265 
276  void unregister_obj(L4::Epiface *o, bool unmap = true) override
277  {
278  L4::Epiface::Stored_cap c;
279 
280  if (!o || !o->obj_cap().is_valid())
281  return;
282 
283  c = o->obj_cap();
284 
285  // make sure unhandled ipc ends up with the null handler
287  todo.add(~3UL, reinterpret_cast<l4_umword_t>(o),
288  ~0UL, reinterpret_cast<l4_umword_t>((L4::Epiface*)&_null_handler));
289  _server->modify_senders(todo);
290 
291  if (unmap)
292  L4::Cap<L4::Task>(L4Re::This_task)->unmap(c.fpage(), L4_FP_ALL_SPACES);
293 
294  // we use bit 4 to indicated an internally allocated cap
295  if (c.managed())
296  cap_alloc.free(c);
297 
299  }
300 };
301 
305 template< typename LOOP_HOOKS = L4::Ipc_svr::Default_loop_hooks >
306 class Registry_server : public L4::Server<LOOP_HOOKS>
307 {
308 private:
310  Object_registry _registry;
311 
312 public:
318  Registry_server() : Base(l4_utcb()), _registry(this)
319  {}
320 
329  L4::Cap<L4::Factory> factory)
330  : Base(utcb), _registry(this, server, factory)
331  {}
332 
334  Object_registry const *registry() const { return &_registry; }
336  Object_registry *registry() { return &_registry; }
337 
342  { Base::template loop<L4::Runtime_error, Object_registry &>(_registry); }
343 };
344 
345 }}
C++ interface of the initial environment that is provided to an L4 task.
Definition: env:86
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition: env:103
L4::Cap< T > get_cap(char const *name, unsigned l) const noexcept
Get the capability selector for the object named name.
Definition: env:204
bool free(L4::Cap< void > cap, l4_cap_idx_t task=L4_INVALID_CAP, unsigned unmap_flags=L4_FP_ALL_SPACES) noexcept
Free the capability.
A registry that manages server objects and their attached IPC gates for a single server loop for a sp...
Definition: object_registry:55
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.
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:92
L4::Cap< void > register_obj(L4::Epiface *o, char const *service) override
Register a new server object to a pre-allocated receive endpoint.
L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o) override
Register a handler for an interrupt.
L4::Cap< void > register_obj(L4::Epiface *o) override
Register a new server object on a newly allocated capability.
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:78
void unregister_obj(L4::Epiface *o, bool unmap=true) override
Remove a server object from the handler list.
A server loop object which has a Object_registry included.
void L4_NORETURN loop()
Start the server loop.
Registry_server()
Create a new server loop object for the main thread of the task.
Object_registry const * registry() const
Return registry of this server loop.
Object_registry * registry()
Return registry of this server loop.
Registry_server(l4_utcb_t *utcb, L4::Cap< L4::Thread > server, L4::Cap< L4::Factory > factory)
Create a new server loop object for an arbitrary thread and factory.
This registry returns the corresponding server object based on the label of an Ipc_gate.
Definition: ipc_epiface:542
bool is_valid() const noexcept
Test whether the capability is a valid capability index (i.e., not L4_INVALID_CAP).
Definition: capability.h:60
l4_msgtag_t create_gate(Cap< void > const &target_cap, Cap< Thread > const &thread_cap, l4_umword_t label, l4_utcb_t *utcb=l4_utcb()) noexcept
Create a new IPC gate.
Definition: factory:416
S create(Cap< void > target, long obj, l4_utcb_t *utcb=l4_utcb()) noexcept
Generic create call to the factory.
Definition: factory:277
Interface for server-loop related functions.
Definition: ipc_epiface:48
L4::Type_info::Demand Demand
Data type expressing server-side demand for receive buffers.
Definition: ipc_epiface:55
virtual int alloc_buffer_demand(Demand const &demand)=0
Tells the server to allocate buffers for the given demand.
Interface for kernel objects that allow to receive IPC from them.
Definition: rcv_endpoint:43
Abstract interface for object registries.
Definition: ipc_epiface:331
virtual L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o)=0
Register o as server-side object for asynchronous IRQs.
Basic server loop for handling client requests.
Wrapper class for modifying senders.
Definition: thread:335
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:367
l4_msgtag_t modify_senders(Modify_senders const &todo) noexcept
Apply sender modification rules.
Definition: thread:394
#define L4_NORETURN
Noreturn function attribute.
Definition: compiler.h:206
Environment interface.
Base exceptions.
Common factory related definitions.
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:52
long l4_error(l4_msgtag_t tag) L4_NOTHROW
Return error code of a system call return message tag or the tag label.
Definition: ipc.h:520
@ L4_FP_ALL_SPACES
Flag to tell the unmap operation to unmap all child mappings including the mapping in the invoked tas...
Definition: consts.h:165
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition: utcb.h:67
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
Definition: utcb.h:340
The C++ IPC gate interface.
_Cap_alloc & cap_alloc
Capability allocator.
L4Re C++ Interfaces.
Definition: cmd_control:15
Constants.
Epiface implementation for Kobject-based interface implementations.
Definition: ipc_epiface:516
Base class for interface implementations.
Definition: ipc_epiface:154
Stored_cap obj_cap() const
Get the capability to the kernel object belonging to this object.
Definition: ipc_epiface:214
virtual Demand get_buffer_demand() const =0
Get the server-side receive buffer demand for this object.
int set_server(Server_iface *srv, Cap< void > cap, bool managed=false)
Set server registration info for the object.
Definition: ipc_epiface:232
T::__Kobject_typeid::Demand Demand
Data type expressing the static demand of receive buffers in a server.
Definition: __typeinfo.h:632
Common thread related definitions.
Common task related definitions.
Capability allocator.
Unique_cap / Unique_del_cap.