L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
ipc_server_loop
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * Copyright (C) 2015, 2017, 2019, 2021-2022 Kernkonzept GmbH.
4 * Author(s): Alexander Warg <alexander.warg@kernkonzept.com>
5 *
6 * This file is distributed under the terms of the GNU General Public
7 * License, version 2. Please see the COPYING-GPL-2 file for details.
8 *
9 * As a special exception, you may use this file as part of a free software
10 * library without restriction. Specifically, if other files instantiate
11 * templates or use macros or inline functions from this file, or you compile
12 * this file and link it with other files to produce an executable, this
13 * file does not by itself cause the resulting executable to be covered by
14 * the GNU General Public License. This exception does not however
15 * invalidate any other reasons why the executable file might be covered by
16 * the GNU General Public License.
17 */
18#pragma once
19
20#include "ipc_epiface"
21
22namespace L4 {
23
35namespace Ipc_svr {
36
55
62{ static void error(l4_msgtag_t, l4_utcb_t *) {} };
63
70{ static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; } };
71
78{
79 static Reply_mode before_reply(l4_msgtag_t, l4_utcb_t *)
80 { return Reply_compound; }
81};
82
89{ static void setup_wait(l4_utcb_t *, Reply_mode) {} };
90
98template< typename R >
100{
102 R &r;
103
106
109 { return r.dispatch(tag, obj, utcb); }
110};
111
119template< typename R >
121{
123 R *r;
124
126 Direct_dispatch(R *r) : r(r) {}
127
129 l4_msgtag_t operator () (l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
130 { return r->dispatch(tag, obj, utcb); }
131};
132
133#ifdef __EXCEPTIONS
143template< typename R, typename Exc> // = L4::Runtime_error>
144struct Exc_dispatch : private Direct_dispatch<R>
145{
148
153 {
154 try
155 {
156 return Direct_dispatch<R>::operator () (tag, obj, utcb);
157 }
158 catch (Exc &e)
159 {
160 return l4_msgtag(e.err_no(), 0, 0, 0);
161 }
162 catch (int err)
163 {
164 return l4_msgtag(err, 0, 0, 0);
165 }
166 catch (long err)
167 {
168 return l4_msgtag(err, 0, 0, 0);
169 }
170 }
171};
172#endif
173
185{
186public:
191 int alloc_buffer_demand(Demand const &demand) override
192 {
193 if (!demand.no_demand())
194 return -L4_ENOMEM;
195 return L4_EOK;
196 }
197
199 L4::Cap<void> get_rcv_cap(int) const override
200 { return L4::Cap<void>::Invalid; }
201
203 int realloc_rcv_cap(int) override
204 { return -L4_ENOMEM; }
205
208 { return -L4_ENOSYS; }
209
211 int remove_timeout(Timeout *) override
212 { return -L4_ENOSYS; }
213
214protected:
216 unsigned first_free_br() const
217 { return 1; }
218
221 {
222 l4_buf_regs_t *br = l4_utcb_br_u(utcb);
223 br->bdr = 0;
224 br->br[0] = 0;
225 }
226};
227
240
241}
242
257template< typename LOOP_HOOKS = Ipc_svr::Default_loop_hooks >
258class Server :
259 public LOOP_HOOKS
260{
261public:
268 /* Internal note: After all users have been converted, remove this
269 * constructor. Also remove the constructor below then. */
270 explicit Server(l4_utcb_t *)
271 L4_DEPRECATED("Do not specify the UTCB with the constructor. "
272 "Supply it on the loop function if needed.")
273 {}
274
278 /* Internal note: Remove this constructor when the above deprecated
279 * constructor with the UTCB pointer is also removed. */
281
288 template< typename DISPATCH >
289 inline L4_NORETURN void internal_loop(DISPATCH dispatch, l4_utcb_t *);
290
294 template< typename R >
297
298#ifdef __EXCEPTIONS
305 template< typename EXC, typename R >
306 inline L4_NORETURN void loop(R r, l4_utcb_t *u = l4_utcb())
307 {
309 // function will never return
310 }
311#endif
312protected:
315};
316
317template< typename L >
318inline l4_msgtag_t
320{
321 if (reply.label() != -L4_ENOREPLY)
322 {
323 Ipc_svr::Reply_mode m = this->before_reply(reply, utcb);
325 {
326 this->setup_wait(utcb, m);
327 return l4_ipc_reply_and_wait(utcb, reply, p, this->timeout());
328 }
329 else
330 {
331 l4_msgtag_t res = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, utcb, reply, this->timeout());
332 if (res.has_error())
333 return res;
334 }
335 }
336 this->setup_wait(utcb, Ipc_svr::Reply_separate);
337 return l4_ipc_wait(utcb, p, this->timeout());
338}
339
340template< typename L >
341template< typename DISPATCH >
342inline L4_NORETURN void
343Server<L>::internal_loop(DISPATCH dispatch, l4_utcb_t *utcb)
344{
345 l4_msgtag_t res;
346 l4_umword_t p;
347 l4_msgtag_t r = l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
348
349 while (true)
350 {
351 res = reply_n_wait(r, &p, utcb);
352 if (res.has_error())
353 {
354 this->error(res, utcb);
355 r = l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
356 continue;
357 }
358
359 r = dispatch(res, p, utcb);
360 }
361}
362
363} // namespace L4
C++ interface for capabilities.
Definition capability.h:219
Empty implementation of Server_iface.
L4::Cap< void > get_rcv_cap(int) const override
Returns L4::Cap<void>::Invalid, we have no buffer management.
int remove_timeout(Timeout *) override
Returns -L4_ENOSYS, we have no timeout queue.
int alloc_buffer_demand(Demand const &demand) override
Tells the server to allocate buffers for the given demand.
unsigned first_free_br() const
Returns 1 as first free buffer.
int realloc_rcv_cap(int) override
Returns -L4_ENOMEM, we have no buffer management.
int add_timeout(Timeout *, l4_kernel_clock_t) override
Returns -L4_ENOSYS, we have no timeout queue.
void setup_wait(l4_utcb_t *utcb, L4::Ipc_svr::Reply_mode)
Setup wait function for the server loop (Server<>).
Interface for server-loop related functions.
Definition ipc_epiface:48
Callback interface for Timeout_queue.
Basic server loop for handling client requests.
l4_msgtag_t reply_n_wait(l4_msgtag_t reply, l4_umword_t *p, l4_utcb_t *)
Internal implementation for reply and wait.
Server()
Initializes the server loop.
L4_NORETURN void internal_loop(DISPATCH dispatch, l4_utcb_t *)
The server loop.
L4_NORETURN void loop(R r, l4_utcb_t *u=l4_utcb())
Server loop with internal exception handling.
L4_NORETURN void loop_noexc(R r, l4_utcb_t *u=l4_utcb())
Server loop without exception handling.
Server(l4_utcb_t *)
Initializes the server loop.
Data type for expressing the needed receive buffers at the server-side of an interface.
Definition __typeinfo.h:518
bool no_demand() const noexcept
Definition __typeinfo.h:543
Reply_mode
Reply mode for server loop.
@ Reply_separate
Server shall call reply and wait separately.
@ Reply_compound
Server shall use a compound reply and wait (fast).
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:51
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition l4int.h:64
@ L4_INVALID_CAP
Invalid capability selector.
Definition consts.h:168
@ L4_ENOSYS
No sys.
Definition err.h:61
@ L4_ENOREPLY
No reply.
Definition err.h:66
@ L4_EOK
Ok.
Definition err.h:43
@ L4_ENOMEM
No memory.
Definition err.h:50
l4_msgtag_t l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag, l4_umword_t *label, l4_timeout_t timeout) L4_NOTHROW
Reply and wait operation (uses the reply capability).
Definition ipc.h:583
l4_msgtag_t l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag, l4_timeout_t timeout) L4_NOTHROW
Send a message to an object (do not wait for a reply).
Definition ipc.h:597
l4_msgtag_t l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *label, l4_timeout_t timeout) L4_NOTHROW
Wait for an incoming message from any possible sender.
Definition ipc.h:604
@ L4_SYSF_REPLY
Reply flag.
Definition consts.h:115
l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, unsigned flags) L4_NOTHROW
Create a message tag from the specified values.
Definition types.h:428
#define L4_IPC_SEND_TIMEOUT_0
0 send timeout
Definition __timeout.h:86
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
#define L4_NORETURN
Noreturn function attribute.
Definition compiler.h:218
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition compiler.h:301
L4 low-level kernel interface.
Definition io_regblock.h:19
Mix in for LOOP_HOOKS to always use compound reply and wait.
Mix in for LOOP_HOOKS for setup_wait no op.
Mix in for LOOP_HOOKS to use a 0 send and a infinite receive timeout.
R * r
stores a pointer to the registry object
Direct_dispatch(R *r)
Make a direct dispatcher.
Direct dispatch helper, for forwarding dispatch calls to a registry R.
R & r
stores a reference to the registry object
l4_msgtag_t operator()(l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
call operator forwarding to r.dispatch()
Direct_dispatch(R &r)
Make a direct dispatcher.
Dispatch helper wrapping try {} catch {} around the dispatch call.
Exc_dispatch(R r)
Make an exception handling dispatcher.
l4_msgtag_t operator()(l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
Dispatch the call via Direct_dispatch<R>() and handle exceptions.
Mix in for LOOP_HOOKS to ignore IPC errors.
Encapsulation of the buffer-registers block in the UTCB.
Definition utcb.h:94
l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE]
Buffer registers.
Definition utcb.h:99
l4_umword_t bdr
Buffer descriptor.
Definition utcb.h:96
Message tag data structure.
Definition types.h:164
long label() const L4_NOTHROW
Get the protocol value.
Definition types.h:168
unsigned has_error() const L4_NOTHROW
Test if flags indicate an error.
Definition types.h:195
Timeout pair.
Definition __timeout.h:61