Loading...
Searching...
No Matches
ipc_server_loop
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* Copyright (C) 2015, 2017, 2019, 2021-2024 Kernkonzept GmbH.
* Author(s): Alexander Warg <alexander.warg@kernkonzept.com>
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include "ipc_epiface"
namespace L4 {
namespace Ipc_svr {
enum Reply_mode
{
Reply_compound,
Reply_separate
};
struct Ignore_errors
{ static void error(l4_msgtag_t, l4_utcb_t *) {} };
struct Default_timeout
{ static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; } };
struct Compound_reply
{
static Reply_mode before_reply(l4_msgtag_t, l4_utcb_t *)
{ return Reply_compound; }
};
struct Default_setup_wait
{ static void setup_wait(l4_utcb_t *, Reply_mode) {} };
template< typename R >
struct Direct_dispatch
{
R &r;
Direct_dispatch(R &r) : r(r) {}
l4_msgtag_t operator () (l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
{ return r.dispatch(tag, obj, utcb); }
};
template< typename R >
struct Direct_dispatch<R*>
{
R *r;
Direct_dispatch(R *r) : r(r) {}
l4_msgtag_t operator () (l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
{ return r->dispatch(tag, obj, utcb); }
};
#ifdef __EXCEPTIONS
template< typename R, typename Exc> // = L4::Runtime_error>
struct Exc_dispatch : private Direct_dispatch<R>
{
Exc_dispatch(R r) : Direct_dispatch<R>(r) {}
l4_msgtag_t operator () (l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
{
try
{
return Direct_dispatch<R>::operator () (tag, obj, utcb);
}
catch (Exc &e)
{
return l4_msgtag(e.err_no(), 0, 0, 0);
}
catch (int err)
{
return l4_msgtag(err, 0, 0, 0);
}
catch (long err)
{
return l4_msgtag(err, 0, 0, 0);
}
}
};
template< typename R, typename Exc, typename Printer >
struct Dbg_dispatch : private Direct_dispatch<R>
{
Dbg_dispatch(R r, Printer p) : Direct_dispatch<R>(r), _printer(p) {}
l4_msgtag_t operator () (l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
{
try
{
return Direct_dispatch<R>::operator () (tag, obj, utcb);
}
catch (Exc &e)
{
_printer.printf("Error in handling IPC: %s: %s\n", e.str(),
e.extra_str());
return l4_msgtag(e.err_no(), 0, 0, 0);
}
catch (int err)
{
_printer.printf("Error in handling IPC: %d (%s)\n", err,
l4sys_errtostr(err));
return l4_msgtag(err, 0, 0, 0);
}
catch (long err)
{
_printer.printf("Error in handling IPC: %ld (%s)\n", err,
l4sys_errtostr(err));
return l4_msgtag(err, 0, 0, 0);
}
}
Printer _printer;
};
#endif
class Br_manager_no_buffers : public Server_iface
{
public:
int alloc_buffer_demand(Demand const &demand) override
{
if (!demand.no_demand())
return -L4_ENOMEM;
return L4_EOK;
}
L4::Cap<void> get_rcv_cap(int) const override
{ return L4::Cap<void>::Invalid; }
int realloc_rcv_cap(int) override
{ return -L4_ENOMEM; }
int add_timeout(Timeout *, l4_kernel_clock_t) override
{ return -L4_ENOSYS; }
int remove_timeout(Timeout *) override
{ return -L4_ENOSYS; }
protected:
unsigned first_free_br() const
{ return 1; }
void setup_wait(l4_utcb_t *utcb, L4::Ipc_svr::Reply_mode)
{
l4_buf_regs_t *br = l4_utcb_br_u(utcb);
br->bdr = 0;
br->br[0] = 0;
}
};
struct Default_loop_hooks :
public Ignore_errors, public Default_timeout, public Compound_reply,
Br_manager_no_buffers
{};
}
template< typename LOOP_HOOKS = Ipc_svr::Default_loop_hooks >
class Server :
public LOOP_HOOKS
{
public:
/* Internal note: After all users have been converted, remove this
* constructor. Also remove the constructor below then. */
explicit Server(l4_utcb_t *)
L4_DEPRECATED("Do not specify the UTCB with the constructor. "
"Supply it on the loop function if needed.")
{}
/* Internal note: Remove this constructor when the above deprecated
* constructor with the UTCB pointer is also removed. */
Server() {}
template< typename DISPATCH >
inline L4_NORETURN void internal_loop(DISPATCH dispatch, l4_utcb_t *);
template< typename R >
inline L4_NORETURN void loop_noexc(R r, l4_utcb_t *u = l4_utcb())
{ internal_loop(Ipc_svr::Direct_dispatch<R>(r), u); }
#ifdef __EXCEPTIONS
template< typename EXC, typename R >
inline L4_NORETURN void loop(R r, l4_utcb_t *u = l4_utcb())
{
internal_loop(Ipc_svr::Exc_dispatch<R, EXC>(r), u);
// function will never return
}
template< typename EXC, typename R, typename Printer >
inline L4_NORETURN void loop_dbg(R r, Printer p, l4_utcb_t *u = l4_utcb())
{
internal_loop(Ipc_svr::Dbg_dispatch<R, EXC, Printer>(r, p), u);
// function will never return
}
#endif
protected:
inline l4_msgtag_t reply_n_wait(l4_msgtag_t reply, l4_umword_t *p, l4_utcb_t *);
};
template< typename L >
inline l4_msgtag_t
Server<L>::reply_n_wait(l4_msgtag_t reply, l4_umword_t *p, l4_utcb_t *utcb)
{
if (reply.label() != -L4_ENOREPLY)
{
Ipc_svr::Reply_mode m = this->before_reply(reply, utcb);
if (m == Ipc_svr::Reply_compound)
{
this->setup_wait(utcb, m);
return l4_ipc_reply_and_wait(utcb, reply, p, this->timeout());
}
else
{
l4_msgtag_t res = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, utcb, reply, this->timeout());
if (res.has_error())
return res;
}
}
this->setup_wait(utcb, Ipc_svr::Reply_separate);
return l4_ipc_wait(utcb, p, this->timeout());
}
template< typename L >
template< typename DISPATCH >
inline L4_NORETURN void
Server<L>::internal_loop(DISPATCH dispatch, l4_utcb_t *utcb)
{
l4_msgtag_t res;
l4_umword_t p;
l4_msgtag_t r = l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
while (true)
{
res = reply_n_wait(r, &p, utcb);
if (res.has_error())
{
this->error(res, utcb);
r = l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
continue;
}
r = dispatch(res, p, utcb);
}
}
} // namespace L4
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::Br_manager_no_buffers
Empty implementation of Server_iface.
Definition ipc_server_loop:234
L4::Ipc_svr::Br_manager_no_buffers::get_rcv_cap
L4::Cap< void > get_rcv_cap(int) const override
Returns L4::Cap<void>::Invalid, we have no buffer management.
Definition ipc_server_loop:248
L4::Ipc_svr::Br_manager_no_buffers::remove_timeout
int remove_timeout(Timeout *) override
Returns -L4_ENOSYS, we have no timeout queue.
Definition ipc_server_loop:260
L4::Ipc_svr::Br_manager_no_buffers::alloc_buffer_demand
int alloc_buffer_demand(Demand const &demand) override
Tells the server to allocate buffers for the given demand.
Definition ipc_server_loop:240
L4::Ipc_svr::Br_manager_no_buffers::first_free_br
unsigned first_free_br() const
Returns 1 as first free buffer.
Definition ipc_server_loop:265
L4::Ipc_svr::Br_manager_no_buffers::realloc_rcv_cap
int realloc_rcv_cap(int) override
Returns -L4_ENOMEM, we have no buffer management.
Definition ipc_server_loop:252
L4::Ipc_svr::Br_manager_no_buffers::add_timeout
int add_timeout(Timeout *, l4_kernel_clock_t) override
Returns -L4_ENOSYS, we have no timeout queue.
Definition ipc_server_loop:256
L4::Ipc_svr::Br_manager_no_buffers::setup_wait
void setup_wait(l4_utcb_t *utcb, L4::Ipc_svr::Reply_mode)
Setup wait function for the server loop (Server<>).
Definition ipc_server_loop:269
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::Timeout
Callback interface for Timeout_queue.
Definition ipc_timeout_queue:19
L4::Server::loop_dbg
L4_NORETURN void loop_dbg(R r, Printer p, l4_utcb_t *u=l4_utcb())
Server loop with internal exception handling including message printing.
Definition ipc_server_loop:368
L4::Server::reply_n_wait
l4_msgtag_t reply_n_wait(l4_msgtag_t reply, l4_umword_t *p, l4_utcb_t *)
Internal implementation for reply and wait.
Definition ipc_server_loop:381
L4::Server::Server
Server()
Initializes the server loop.
Definition ipc_server_loop:329
L4::Server::internal_loop
L4_NORETURN void internal_loop(DISPATCH dispatch, l4_utcb_t *)
The server loop.
Definition ipc_server_loop:405
L4::Server::loop
L4_NORETURN void loop(R r, l4_utcb_t *u=l4_utcb())
Server loop with internal exception handling.
Definition ipc_server_loop:355
L4::Server::loop_noexc
L4_NORETURN void loop_noexc(R r, l4_utcb_t *u=l4_utcb())
Server loop without exception handling.
Definition ipc_server_loop:344
L4::Server::Server
Server(l4_utcb_t *)
Initializes the server loop.
Definition ipc_server_loop:319
L4::Type_info::Demand::no_demand
bool no_demand() const noexcept
Definition __typeinfo.h:532
L4::Ipc_svr::Reply_mode
Reply_mode
Reply mode for server loop.
Definition ipc_server_loop:47
L4::Ipc_svr::Reply_separate
@ Reply_separate
Server shall call reply and wait separately.
Definition ipc_server_loop:49
L4::Ipc_svr::Reply_compound
@ Reply_compound
Server shall use a compound reply and wait (fast).
Definition ipc_server_loop:48
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_kernel_clock_t
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition l4int.h:53
L4_INVALID_CAP
@ L4_INVALID_CAP
Invalid capability selector.
Definition consts.h:153
L4_ENOSYS
@ L4_ENOSYS
No sys.
Definition err.h:50
L4_ENOREPLY
@ L4_ENOREPLY
No reply.
Definition err.h:55
L4_EOK
@ L4_EOK
Ok.
Definition err.h:32
L4_ENOMEM
@ L4_ENOMEM
No memory.
Definition err.h:39
l4_ipc_reply_and_wait
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:572
l4_ipc_send
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:586
l4_ipc_wait
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:593
L4_SYSF_REPLY
@ L4_SYSF_REPLY
Reply flag.
Definition consts.h:100
l4_msgtag
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:405
L4_IPC_SEND_TIMEOUT_0
#define L4_IPC_SEND_TIMEOUT_0
0 send timeout
Definition __timeout.h:78
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
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
L4::Ipc_svr
Helper classes for L4::Server instantiation.
Definition ipc_epiface:25
L4
L4 low-level kernel interface.
Definition l4sys-l4f-groups.dox:50
L4::Ipc_svr::Compound_reply
Mix in for LOOP_HOOKS to always use compound reply and wait.
Definition ipc_server_loop:74
L4::Ipc_svr::Dbg_dispatch
Dispatch helper that, in addition to what Exc_dispatch does, prints exception messages.
Definition ipc_server_loop:185
L4::Ipc_svr::Dbg_dispatch::operator()
l4_msgtag_t operator()(l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
Dispatch the call via Direct_dispatch<R>(), handle exceptions, and print the exception message.
Definition ipc_server_loop:193
L4::Ipc_svr::Dbg_dispatch::Dbg_dispatch
Dbg_dispatch(R r, Printer p)
Make an exception handling dispatcher.
Definition ipc_server_loop:187
L4::Ipc_svr::Default_loop_hooks
Default LOOP_HOOKS.
Definition ipc_server_loop:288
L4::Ipc_svr::Default_setup_wait
Mix in for LOOP_HOOKS for setup_wait no op.
Definition ipc_server_loop:85
L4::Ipc_svr::Default_timeout
Mix in for LOOP_HOOKS to use a 0 send and a infinite receive timeout.
Definition ipc_server_loop:66
L4::Ipc_svr::Direct_dispatch< R * >::r
R * r
stores a pointer to the registry object
Definition ipc_server_loop:119
L4::Ipc_svr::Direct_dispatch< R * >::Direct_dispatch
Direct_dispatch(R *r)
Make a direct dispatcher.
Definition ipc_server_loop:122
L4::Ipc_svr::Direct_dispatch
Direct dispatch helper, for forwarding dispatch calls to a registry R.
Definition ipc_server_loop:96
L4::Ipc_svr::Direct_dispatch::r
R & r
stores a reference to the registry object
Definition ipc_server_loop:98
L4::Ipc_svr::Direct_dispatch::operator()
l4_msgtag_t operator()(l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
call operator forwarding to r.dispatch()
Definition ipc_server_loop:104
L4::Ipc_svr::Direct_dispatch::Direct_dispatch
Direct_dispatch(R &r)
Make a direct dispatcher.
Definition ipc_server_loop:101
L4::Ipc_svr::Exc_dispatch
Dispatch helper wrapping try {} catch {} around the dispatch call.
Definition ipc_server_loop:141
L4::Ipc_svr::Exc_dispatch::Exc_dispatch
Exc_dispatch(R r)
Make an exception handling dispatcher.
Definition ipc_server_loop:143
L4::Ipc_svr::Exc_dispatch::operator()
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.
Definition ipc_server_loop:148
L4::Ipc_svr::Ignore_errors
Mix in for LOOP_HOOKS to ignore IPC errors.
Definition ipc_server_loop:58
l4_buf_regs_t
Encapsulation of the buffer-registers block in the UTCB.
Definition utcb.h:83
l4_buf_regs_t::br
l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE]
Buffer registers.
Definition utcb.h:88
l4_buf_regs_t::bdr
l4_umword_t bdr
Buffer descriptor.
Definition utcb.h:85
l4_msgtag_t
Message tag data structure.
Definition types.h:154
l4_msgtag_t::label
long label() const L4_NOTHROW
Get the protocol value.
Definition types.h:158
l4_msgtag_t::has_error
bool has_error() const L4_NOTHROW
Test if flags indicate an error.
Definition types.h:191
l4_timeout_t
Timeout pair.
Definition __timeout.h:53