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 {
using result_type = T; };
320 Return_tag = L4::Types::Same_v<R, l4_msgtag_t>
324 using type = Rpc_inline_call;
328 using class_type = CLASS;
330 using result_type =
typename Result<R>::result_type;
332 using ipc_type = R (ARGS...);
334 using func_type = result_type (
typename _Elem<ARGS>::arg_type...);
337 using flags_type = FLAGS;
339 template<
typename RES>
343 template<
typename RES>
345 return_ipc_err(l4_msgtag_t tag,
l4_utcb_t const *)
noexcept {
return tag; }
347 template<
typename RES>
349 return_code(l4_msgtag_t tag)
noexcept {
return tag; }
351 template<
typename RES>
353 return_err(
long err)
noexcept {
return err; }
355 template<
typename RES>
357 return_ipc_err(l4_msgtag_t,
l4_utcb_t *utcb)
noexcept
360 template<
typename RES>
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 using class_type =
typename IPC::class_type;
391 using result_type =
typename IPC::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 using type = L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args>; \
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 using type = L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args>; \
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 using type = L4::Ipc::Msg::Rpc_call<name##_t, Class, res args>; \
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 using type = L4::Ipc::Msg::Rpc_call<name##_t, Class, res args>; \
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<Phase PHASE>
578 static constexpr int write(
char *,
int offset,
int)
noexcept
581 template<Phase PHASE>
582 static constexpr int read(
char *,
int offset,
int)
noexcept
588template<
typename A,
typename ...M>
589struct Buf<A, M...> : Buf<M...>
591 using Base = Buf<M...>;
593 using xmit = Clnt_xmit<A>;
594 using arg_type =
typename _Elem<A>::arg_type;
595 using plain = Detail::_Plain<arg_type>;
596 static constexpr bool Is_input = _Elem<A>::Is_input;
597 static constexpr bool Is_output = _Elem<A>::Is_output;
599 template<Phase PHASE>
601 write(
char *base,
int offset,
int limit,
602 arg_type a,
typename _Elem<M>::arg_type ...m)
noexcept
604 if constexpr (PHASE == Phase::Data && Is_input)
605 offset = xmit::to_msg_data(base, offset, limit, plain::deref(a));
606 else if constexpr (PHASE == Phase::Items && Is_input)
607 offset = xmit::to_msg_items(base, offset, limit, plain::deref(a));
608 else if constexpr (PHASE == Phase::Buffers && Is_output)
609 offset = xmit::to_msg_buffers(base, offset, limit, plain::deref(a));
611 return Base::template write<PHASE>(base, offset, limit, m...);
614 template<Phase PHASE>
616 read(
char *base,
int offset,
int limit,
617 arg_type a,
typename _Elem<M>::arg_type ...m)
noexcept
621 if constexpr (Is_output)
623 static_assert(PHASE == Phase::Data || PHASE == Phase::Items);
624 if constexpr (PHASE == Phase::Data)
625 r = xmit::from_msg_data(base, offset, limit, plain::deref(a));
627 r = xmit::from_msg_items(base, offset, limit, plain::deref(a));
631 return Base::template read<PHASE>(base, r, limit, m...);
633 if (_Elem<A>::Is_optional)
634 return Base::template read<PHASE>(base, offset, limit, m...);
640template <
typename ...ARGS>
struct _Part
643 using Data = Buf<ARGS...>;
645 template<Phase PHASE>
646 static int write(
void *b,
int offset,
int limit,
647 typename _Elem<ARGS>::arg_type ...m)
noexcept
649 char *buf =
static_cast<char *
>(b);
650 int r = Data::template write<PHASE>(buf, offset, limit, m...);
656 template<Phase PHASE>
657 static int read(
void *b,
int offset,
int limit,
658 typename _Elem<ARGS>::arg_type ...m)
noexcept
660 char *buf =
static_cast<char *
>(b);
661 int r = Data::template read<PHASE>(buf, offset, limit, m...);
674template<
typename IPC_TYPE,
typename OPCODE =
void>
678template<
typename R,
typename ...ARGS>
679struct Part<R (ARGS...), void> : _Part<ARGS...>
682 using Data = Buf<ARGS...>;
685 static int write_op(
void *b,
int offset,
int limit,
687 typename _Elem<ARGS>::arg_type ...m)
noexcept
689 char *buf =
static_cast<char *
>(b);
690 int r = Data::template write<Phase::Data>(buf, offset, limit, m...);
698template<
typename OPCODE,
typename R,
typename ...ARGS>
699struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
701 using opcode_type = OPCODE;
703 using Data = Buf<opcode_type, ARGS...>;
706 static int write_op(
void *b,
int offset,
int limit,
707 opcode_type op,
typename _Elem<ARGS>::arg_type ...m)
noexcept
709 char *buf =
static_cast<char *
>(b);
710 int r = Data::template write<Phase::Data>(buf, offset, limit, op, m...);
725template<
typename OP,
typename CLASS,
typename FLAGS,
typename R,
728Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
729 call(L4::Cap<CLASS> cap,
730 typename _Elem<ARGS>::arg_type ...a,
733 using namespace Ipc::Msg;
735 using Rpcs =
typename Kobject_typeid<CLASS>::Iface::Rpcs;
736 using Opt =
typename Rpcs::template Rpc<OP>;
737 using Args = Detail::Part<ipc_type, typename Rpcs::opcode_type>;
743 Args::write_op(mrs->
mr, 0, Mr_bytes, Opt::Opcode, a...);
746 return return_err<R>(send_bytes);
748 send_bytes = align_to<l4_umword_t>(send_bytes);
749 int const send_words = send_bytes /
Word_bytes;
752 Args::template write<Phase::Items>(&mrs->
mr[send_words], 0,
753 Mr_bytes - send_bytes, a...);
756 return return_err<R>(item_bytes);
769 Args::template write<Phase::Buffers>(brs->
br, 0, Br_bytes - Word_bytes,
773 return return_err<R>(bytes);
781 t =
l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
783 if (flags_type::Is_call)
789 return return_ipc_err<R>(t, utcb);
798 return return_ipc_err<R>(t, utcb);
805 return return_err<R>(r);
810 int err = Args::template read<Phase::Data>(mrs->
mr, 0, rcv_bytes, a...);
818 err = Args::template read<Phase::Items>(&mrs->
mr[t.
words()], 0, item_limit,
824 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.
typename Enable_if< Condition, T >::type Enable_if_t
Helper type for Enable_if.
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.