8#pragma GCC system_header
10#include <l4/sys/cxx/ipc_basics>
221namespace L4 {
namespace Ipc {
241 enum { Is_call =
true };
269template<
unsigned RIGHTS>
272 enum { Rights = RIGHTS };
289 enum { Is_call =
false };
306template<
typename OP,
typename CLASS,
typename SIG,
typename FLAGS = Call>
313template<
typename OP,
typename CLASS,
typename FLAGS,
typename R,
315struct L4_EXPORT Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
317 template<
typename T>
struct Result {
typedef T result_type; };
320 Return_tag = L4::Types::Same<R, l4_msgtag_t>::value
324 typedef Rpc_inline_call type;
328 typedef CLASS class_type;
330 typedef typename Result<R>::result_type result_type;
332 typedef R ipc_type (ARGS...);
334 typedef result_type func_type (
typename _Elem<ARGS>::arg_type...);
337 typedef FLAGS flags_type;
339 template<
typename RES>
340 static typename L4::Types::Enable_if< Return_tag, RES >::type
343 template<
typename RES>
344 static typename L4::Types::Enable_if< Return_tag, RES >::type
345 return_ipc_err(l4_msgtag_t tag,
l4_utcb_t const *)
noexcept {
return tag; }
347 template<
typename RES>
348 static typename L4::Types::Enable_if< Return_tag, RES >::type
349 return_code(l4_msgtag_t tag)
noexcept {
return tag; }
351 template<
typename RES>
352 static typename L4::Types::Enable_if< !Return_tag, RES >::type
353 return_err(
long err)
noexcept {
return err; }
355 template<
typename RES>
356 static typename L4::Types::Enable_if< !Return_tag, RES >::type
357 return_ipc_err(l4_msgtag_t,
l4_utcb_t *utcb)
noexcept
360 template<
typename RES>
361 static typename L4::Types::Enable_if< !Return_tag, RES >::type
362 return_code(l4_msgtag_t tag)
noexcept {
return tag.label(); }
364 static R call(L4::Cap<class_type> cap,
365 typename _Elem<ARGS>::arg_type ...a,
373template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
383template<typename IPC, typename SIG> struct _Call;
386template<typename IPC, typename R, typename ...ARGS>
387struct _Call<IPC, R (ARGS...)>
390 typedef typename IPC::class_type class_type;
391 typedef typename IPC::result_type result_type;
394 L4::Cap<class_type> cap() const noexcept
396 return L4::Cap<class_type>(
reinterpret_cast<l4_cap_idx_t>(
this)
402 result_type operator () (ARGS ...a,
l4_utcb_t *utcb =
l4_utcb()) const noexcept
403 {
return IPC::call(cap(), a..., utcb); }
412template<
typename IPC>
struct Call : _Call<IPC, typename IPC::func_type> {};
423struct L4_EXPORT Rpc_call<OP, CLASS, R (ARGS...), FLAGS> :
424 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
426 static R call(L4::Cap<CLASS> cap,
427 typename _Elem<ARGS>::arg_type ...a,
431#define L4_INLINE_RPC_SRV_FORWARD(name) \
432 template<typename OBJ> struct fwd \
435 fwd(OBJ *o) noexcept : o(o) {} \
436 template<typename ...ARGS> \
437 decltype(auto) call(ARGS ...a) noexcept(noexcept(o->op_##name(a...))) \
438 { return o->op_##name(a...); } \
454#define L4_INLINE_RPC_NF(res, name, args...) \
455 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
457 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
458 L4_INLINE_RPC_SRV_FORWARD(name); \
467#define L4_INLINE_RPC_NF_OP(op, res, name, args...) \
468 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
470 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
471 enum { Opcode = (op) }; \
472 L4_INLINE_RPC_SRV_FORWARD(name); \
483#define L4_INLINE_RPC(res, name, args, attr...) res name args
485#define L4_INLINE_RPC(res, name, args...) \
486 L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
498#define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
500#define L4_INLINE_RPC_OP(op, res, name, args...) \
501 L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
511#define L4_RPC_NF(res, name, args...) \
512 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
514 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
515 L4_INLINE_RPC_SRV_FORWARD(name); \
526#define L4_RPC_NF_OP(op, res, name, args...) \
527 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
529 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
530 enum { Opcode = (op) }; \
531 L4_INLINE_RPC_SRV_FORWARD(name); \
542#define L4_RPC(res, name, args, attr...) res name args
544#define L4_RPC(res, name, args...) \
545 L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
557#define L4_RPC_OP(op, res, name, args, attr...) res name args
559#define L4_RPC_OP(op, res, name, args...) \
560 L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
573template<
typename ...ARGS>
577 template<
typename DIR>
578 static constexpr int write(
char *,
int offset,
int)
noexcept
581 template<
typename DIR>
582 static constexpr int read(
char *,
int offset,
int,
l4_ret_t)
noexcept
588template<
typename A,
typename ...M>
589struct Buf<A, M...> : Buf<M...>
591 typedef Buf<M...> Base;
593 typedef Clnt_xmit<A> xmit;
594 typedef typename _Elem<A>::arg_type arg_type;
595 typedef Detail::_Plain<arg_type> plain;
597 template<
typename DIR>
599 write(
char *base,
int offset,
int limit,
600 arg_type a,
typename _Elem<M>::arg_type ...m)
noexcept
602 offset = xmit::to_msg(base, offset, limit, plain::deref(a),
603 typename DIR::dir(),
typename DIR::cls());
604 return Base::template write<DIR>(base, offset, limit, m...);
607 template<
typename DIR>
609 read(
char *base,
int offset,
int limit,
l4_ret_t ret,
610 arg_type a,
typename _Elem<M>::arg_type ...m)
noexcept
612 int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
613 typename DIR::dir(),
typename DIR::cls());
615 return Base::template read<DIR>(base, r, limit, ret, m...);
617 if (_Elem<A>::Is_optional)
618 return Base::template read<DIR>(base, offset, limit, ret, m...);
624template <
typename ...ARGS>
struct _Part
627 typedef Buf<ARGS...> Data;
629 template<
typename DIR>
630 static int write(
void *b,
int offset,
int limit,
631 typename _Elem<ARGS>::arg_type ...m)
noexcept
633 char *buf =
static_cast<char *
>(b);
634 int r = Data::template write<DIR>(buf, offset, limit, m...);
640 template<
typename DIR>
641 static int read(
void *b,
int offset,
int limit,
l4_ret_t ret,
642 typename _Elem<ARGS>::arg_type ...m)
noexcept
644 char *buf =
static_cast<char *
>(b);
645 int r = Data::template read<DIR>(buf, offset, limit, ret, m...);
658template<
typename IPC_TYPE,
typename OPCODE =
void>
662template<
typename R,
typename ...ARGS>
663struct Part<R (ARGS...), void> : _Part<ARGS...>
666 typedef Buf<ARGS...> Data;
669 template<
typename DIR>
670 static int write_op(
void *b,
int offset,
int limit,
672 typename _Elem<ARGS>::arg_type ...m)
noexcept
674 char *buf =
static_cast<char *
>(b);
675 int r = Data::template write<DIR>(buf, offset, limit, m...);
683template<
typename OPCODE,
typename R,
typename ...ARGS>
684struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
686 typedef OPCODE opcode_type;
688 typedef Buf<opcode_type, ARGS...> Data;
691 template<
typename DIR>
692 static int write_op(
void *b,
int offset,
int limit,
693 opcode_type op,
typename _Elem<ARGS>::arg_type ...m)
noexcept
695 char *buf =
static_cast<char *
>(b);
696 int r = Data::template write<DIR>(buf, offset, limit, op, m...);
711template<
typename OP,
typename CLASS,
typename FLAGS,
typename R,
714Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
715 call(L4::Cap<CLASS> cap,
716 typename _Elem<ARGS>::arg_type ...a,
719 using namespace Ipc::Msg;
721 typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
722 typedef typename Rpcs::template Rpc<OP> Opt;
723 typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
729 Args::template write_op<Do_in_data>(mrs->
mr, 0, Mr_bytes,
733 return return_err<R>(send_bytes);
735 send_bytes = align_to<l4_umword_t>(send_bytes);
736 int const send_words = send_bytes /
Word_bytes;
739 Args::template write<Do_in_items>(&mrs->
mr[send_words], 0,
740 Mr_bytes - send_bytes, a...);
743 return return_err<R>(item_bytes);
756 Args::template write<Do_rcv_buffers>(brs->
br, 0, Br_bytes - Word_bytes,
760 return return_err<R>(bytes);
768 t =
l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
770 if (flags_type::Is_call)
776 return return_ipc_err<R>(t, utcb);
785 return return_ipc_err<R>(t, utcb);
792 return return_err<R>(r);
797 int err = Args::template read<Do_out_data>(mrs->
mr, 0, rcv_bytes, r, a...);
805 err = Args::template read<Do_out_items>(&mrs->
mr[t.
words()], 0, item_limit,
811 return return_code<R>(t);
Type information handling.
l4_cap_idx_t cap() const noexcept
Return capability selector.
unsigned long l4_cap_idx_t
Capability selector type.
#define L4_CAP_MASK
Mask to get only the relevant bits of an l4_cap_idx_t.
@ L4_EMSGTOOSHORT
Message too short.
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).
l4_msgtag_t l4_ipc_call(l4_cap_idx_t object, l4_utcb_t *utcb, l4_msgtag_t tag, l4_timeout_t timeout) L4_NOTHROW
Object call (usual invocation).
int l4_ipc_error_code(l4_utcb_t *utcb) L4_NOTHROW
Get the error condition of the last invocation from the TCR.
l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, unsigned flags) L4_NOTHROW
Create a message tag from the specified values.
#define L4_IPC_SEND_TIMEOUT_0
0 send timeout
#define L4_IPC_NEVER
never timeout
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
struct l4_buf_regs_t l4_buf_regs_t
Encapsulation of the buffer-registers block in the UTCB.
union l4_msg_regs_t l4_msg_regs_t
Encapsulation of the message-register block in the UTCB.
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
#define L4_EXPORT
Attribute to mark functions, variables, and data types as being exported from a library.
#define L4_LIKELY(x)
Expression is likely to execute.
L4_CONSTEXPR l4_ret_t l4_ipc_to_errno(unsigned long ipc_error_code) L4_NOTHROW
Get a negative error code for the given IPC error code.
l4_int16_t l4_ret_t
Return value of an IPC call as well as an RPC call.
IPC Message related functionality.
@ Item_bytes
number of bytes for one message item
@ Word_bytes
number of bytes for one message word
IPC related functionality.
L4 low-level kernel interface.
RPC attribute for an RPC call with required rights.
RPC attribute for an RPC call, with zero send timeout.
RPC attribute for a standard RPC call.
RPC attribute for a send-only RPC.
l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE]
Buffer registers.
l4_umword_t bdr
Buffer descriptor.
long label() const L4_NOTHROW
Get the protocol value.
bool has_error() const L4_NOTHROW
Test if flags indicate an error.
unsigned words() const L4_NOTHROW
Get the number of untyped words.
unsigned items() const L4_NOTHROW
Get the number of typed items.
unsigned flags() const L4_NOTHROW
Get the flags value.
l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]
Message registers.