19 #pragma GCC system_header
21 #include <l4/sys/cxx/ipc_basics>
208 namespace L4 {
namespace Ipc {
228 enum { Is_call =
true };
238 static l4_timeout_t timeout() {
return L4_IPC_SEND_TIMEOUT_0; }
256 template<
unsigned RIGHTS>
259 enum { Rights = RIGHTS };
276 enum { Is_call =
false };
293 template<
typename OP,
typename CLASS,
typename SIG,
typename FLAGS = Call>
294 struct L4_EXPORT Rpc_inline_call;
300 template<
typename OP,
typename CLASS,
typename FLAGS,
typename R,
302 struct L4_EXPORT Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
304 template<
typename T>
struct Result {
typedef T result_type; };
311 typedef Rpc_inline_call type;
315 typedef CLASS class_type;
317 typedef typename Result<R>::result_type result_type;
319 typedef R ipc_type (ARGS...);
321 typedef result_type func_type (
typename _Elem<ARGS>::arg_type...);
324 typedef FLAGS flags_type;
326 template<
typename RES>
327 static typename L4::Types::Enable_if< Return_tag, RES >::type
328 return_err(
long err) noexcept {
return l4_msgtag(err, 0, 0, 0); }
330 template<
typename RES>
331 static typename L4::Types::Enable_if< Return_tag, RES >::type
334 template<
typename RES>
335 static typename L4::Types::Enable_if< Return_tag, RES >::type
336 return_code(
l4_msgtag_t tag) noexcept {
return tag; }
338 template<
typename RES>
339 static typename L4::Types::Enable_if< !Return_tag, RES >::type
340 return_err(
long err) noexcept {
return err; }
342 template<
typename RES>
343 static typename L4::Types::Enable_if< !Return_tag, RES >::type
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.label(); }
352 typename _Elem<ARGS>::arg_type ...a,
360 template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
361 struct L4_EXPORT Rpc_call;
370 template<typename IPC, typename SIG> struct _Call;
373 template<typename IPC, typename R, typename ...ARGS>
374 struct _Call<IPC, R (ARGS...)>
377 typedef typename IPC::class_type class_type;
378 typedef typename IPC::result_type result_type;
389 result_type operator () (ARGS ...a,
l4_utcb_t *utcb =
l4_utcb()) const noexcept
390 {
return IPC::call(cap(), a..., utcb); }
399 template<
typename IPC>
struct Call : _Call<IPC, typename IPC::func_type> {};
405 template<
typename OP,
410 struct L4_EXPORT Rpc_call<OP, CLASS, R (ARGS...), FLAGS> :
411 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
414 typename _Elem<ARGS>::arg_type ...a,
418 #define L4_INLINE_RPC_SRV_FORWARD(name) \
419 template<typename OBJ> struct fwd \
422 fwd(OBJ *o) noexcept : o(o) {} \
423 template<typename ...ARGS> long call(ARGS ...a) noexcept(noexcept(o->op_##name(a...))) \
424 { return o->op_##name(a...); } \
440 #define L4_INLINE_RPC_NF(res, name, args...) \
441 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
443 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
444 L4_INLINE_RPC_SRV_FORWARD(name); \
453 #define L4_INLINE_RPC_NF_OP(op, res, name, args...) \
454 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
456 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
457 enum { Opcode = (op) }; \
458 L4_INLINE_RPC_SRV_FORWARD(name); \
469 #define L4_INLINE_RPC(res, name, args, attr...) res name args
471 #define L4_INLINE_RPC(res, name, args...) \
472 L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
484 #define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
486 #define L4_INLINE_RPC_OP(op, res, name, args...) \
487 L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
497 #define L4_RPC_NF(res, name, args...) \
498 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
500 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
501 L4_INLINE_RPC_SRV_FORWARD(name); \
512 #define L4_RPC_NF_OP(op, res, name, args...) \
513 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
515 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
516 enum { Opcode = (op) }; \
517 L4_INLINE_RPC_SRV_FORWARD(name); \
528 #define L4_RPC(res, name, args, attr...) res name args
530 #define L4_RPC(res, name, args...) \
531 L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
543 #define L4_RPC_OP(op, res, name, args, attr...) res name args
545 #define L4_RPC_OP(op, res, name, args...) \
546 L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
559 template<
typename ...ARGS>
563 template<
typename DIR>
564 static constexpr
int write(
char *,
int offset,
int) noexcept
567 template<
typename DIR>
568 static constexpr
int read(
char *,
int offset,
int,
long) noexcept
574 template<
typename A,
typename ...M>
575 struct Buf<A, M...> : Buf<M...>
577 typedef Buf<M...> Base;
579 typedef Clnt_xmit<A> xmit;
580 typedef typename _Elem<A>::arg_type arg_type;
581 typedef Detail::_Plain<arg_type> plain;
583 template<
typename DIR>
585 write(
char *base,
int offset,
int limit,
586 arg_type a,
typename _Elem<M>::arg_type ...m) noexcept
588 offset = xmit::to_msg(base, offset, limit, plain::deref(a),
589 typename DIR::dir(),
typename DIR::cls());
590 return Base::template write<DIR>(base, offset, limit, m...);
593 template<
typename DIR>
595 read(
char *base,
int offset,
int limit,
long ret,
596 arg_type a,
typename _Elem<M>::arg_type ...m) noexcept
598 int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
599 typename DIR::dir(),
typename DIR::cls());
601 return Base::template read<DIR>(base, r, limit, ret, m...);
603 if (_Elem<A>::Is_optional)
604 return Base::template read<DIR>(base, offset, limit, ret, m...);
610 template <
typename ...ARGS>
struct _Part
613 typedef Buf<ARGS...> Data;
615 template<
typename DIR>
616 static int write(
void *b,
int offset,
int limit,
617 typename _Elem<ARGS>::arg_type ...m) noexcept
619 int r = Data::template write<DIR>((
char *)b, offset, limit, m...);
625 template<
typename DIR>
626 static int read(
void *b,
int offset,
int limit,
long ret,
627 typename _Elem<ARGS>::arg_type ...m) noexcept
629 int r = Data::template read<DIR>((
char *)b, offset, limit, ret, m...);
642 template<
typename IPC_TYPE,
typename OPCODE =
void>
646 template<
typename R,
typename ...ARGS>
647 struct Part<R (ARGS...), void> : _Part<ARGS...>
650 typedef Buf<ARGS...> Data;
653 template<
typename DIR>
654 static int write_op(
void *b,
int offset,
int limit,
656 typename _Elem<ARGS>::arg_type ...m) noexcept
658 int r = Data::template write<DIR>((
char *)b, offset, limit, m...);
666 template<
typename OPCODE,
typename R,
typename ...ARGS>
667 struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
669 typedef OPCODE opcode_type;
671 typedef Buf<opcode_type, ARGS...> Data;
674 template<
typename DIR>
675 static int write_op(
void *b,
int offset,
int limit,
676 opcode_type op,
typename _Elem<ARGS>::arg_type ...m) noexcept
678 int r = Data::template write<DIR>((
char *)b, offset, limit, op, m...);
693 template<
typename OP,
typename CLASS,
typename FLAGS,
typename R,
696 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
698 typename _Elem<ARGS>::arg_type ...a,
701 using namespace Ipc::Msg;
703 typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
704 typedef typename Rpcs::template Rpc<OP> Opt;
705 typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
711 Args::template write_op<Do_in_data>(mrs->
mr, 0,
Mr_bytes,
715 return return_err<R>(send_bytes);
717 send_bytes = align_to<l4_umword_t>(send_bytes);
718 int const send_words = send_bytes /
Word_bytes;
721 Args::template write<Do_in_items>(&mrs->
mr[send_words], 0,
725 return return_err<R>(item_bytes);
742 return return_err<R>(bytes);
750 t =
l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
752 if (flags_type::Is_call)
753 t =
l4_ipc_call(cap.cap(), utcb, t, flags_type::timeout());
756 t =
l4_ipc_send(cap.cap(), utcb, t, flags_type::timeout());
758 return return_ipc_err<R>(t, utcb);
767 return return_ipc_err<R>(t, utcb);
774 return return_err<R>(r);
779 int err = Args::template read<Do_out_data>(mrs->
mr, 0, rcv_bytes, r, a...);
787 err = Args::template read<Do_out_items>(&mrs->
mr[t.
words()], 0, item_limit,
793 return return_code<R>(t);