8#pragma GCC system_header
10#include <l4/sys/cxx/ipc_basics>
12#include <l4/sys/cxx/limits>
23template<
typename T>
struct Sizeof {
enum { size =
sizeof(T) }; };
24template<>
struct Sizeof<void> {
enum { size = 0 }; };
29template<
typename ...>
struct Arg_pack
31 template<
typename DIR>
32 unsigned get(
char *,
unsigned offset,
unsigned)
35 template<
typename DIR>
36 unsigned set(
char *,
unsigned offset,
unsigned,
l4_ret_t)
39 template<
typename F,
typename ...ARGS>
40 decltype(
auto) call(F f, ARGS ...args)
41 {
return f(args...); }
43 template<
typename ...>
47 template<
typename O,
typename FUNC,
typename ...ARGS>
48 auto obj_call(O *o, ARGS ...args)
49 ->
decltype(
typename FUNC::template fwd<O>(o).template call<ARGS...>(args...))
51 using Fwd =
typename FUNC::template fwd<O>;
52 using Idl_ret =
typename FUNC::result_type;
53 using Svr_ret =
decltype(Fwd(o).template call<ARGS...>(args...));
54 auto ret = Fwd(o).template call<ARGS...>(args...);
56 using L4::Types::numeric_limits;
59 if constexpr (numeric_limits<Svr_ret>::min() < numeric_limits<Idl_ret>::min())
61 if (
L4_UNLIKELY(ret < numeric_limits<Idl_ret>::min()))
68 if constexpr (numeric_limits<Svr_ret>::max() > numeric_limits<Idl_ret>::max())
70 l4_assert(ret <= numeric_limits<Idl_ret>::max());
71 if (
L4_UNLIKELY(ret > numeric_limits<Idl_ret>::max()))
76 if constexpr (numeric_limits<Svr_ret>::min() < numeric_limits<l4_msgtag_t>::min())
78 if (
L4_UNLIKELY(ret < numeric_limits<l4_msgtag_t>::min()))
81 if constexpr (numeric_limits<Svr_ret>::max() > numeric_limits<l4_msgtag_t>::max())
83 l4_assert(ret <= numeric_limits<l4_msgtag_t>::max());
84 if (
L4_UNLIKELY(ret > numeric_limits<l4_msgtag_t>::max()))
95template<
typename T,
typename SVR_TYPE,
typename ...M>
96struct Svr_arg : Svr_xmit<T>, Arg_pack<M...>
98 using Base = Arg_pack<M...>;
100 using svr_type = SVR_TYPE;
101 using svr_arg_type =
typename _Elem<T>::svr_arg_type;
105 template<
typename DIR>
106 int get(
char *msg,
unsigned offset,
unsigned limit)
108 using ct = Svr_xmit<T>;
109 int r = ct::to_svr(msg, offset, limit, this->v,
110 typename DIR::dir(),
typename DIR::cls());
112 return Base::template get<DIR>(msg, r, limit);
114 if (_Elem<T>::Is_optional)
117 return Base::template get<DIR>(msg, offset, limit);
122 template<
typename DIR>
123 int set(
char *msg,
unsigned offset,
unsigned limit,
l4_ret_t ret)
125 using ct = Svr_xmit<T>;
126 int r = ct::from_svr(msg, offset, limit, ret, this->v,
127 typename DIR::dir(),
typename DIR::cls());
130 return Base::template set<DIR>(msg, r, limit, ret);
133 template<
typename F,
typename ...ARGS>
134 decltype(
auto) call(F f, ARGS ...args)
137 return Base::template
138 call<F, ARGS..., svr_arg_type>(f, args..., this->v);
141 template<
typename ...ARGS>
142 void reply(ARGS &&...args)
145 if constexpr (L4::Types::Same_v<typename Direction<T>::type, Dir_out>
146 || L4::Types::Same_template_v<T, In_out>)
147 reply_consume_arg<ARGS...>(L4::Types::forward<ARGS>(args)...);
149 Base::template reply<ARGS...>(L4::Types::forward<ARGS>(args)...);
152 template<
typename O,
typename FUNC,
typename ...ARGS>
153 decltype(
auto) obj_call(O *o, ARGS ...args)
156 return Base::template
157 obj_call<O, FUNC, ARGS..., svr_arg_type>(o, args..., this->v);
161 template<
typename A,
typename ...ARGS>
162 void reply_consume_arg(A &&a, ARGS &&...args)
164 this->v = L4::Types::move(a);
165 Base::template reply<ARGS...>(L4::Types::forward<ARGS>(args)...);
174template<
typename T,
typename ...M>
175struct Svr_arg<T, void, M...> : Arg_pack<M...>
178template<
typename A,
typename ...M>
179struct Arg_pack<A, M...> : Svr_arg<A, typename _Elem<A>::svr_type, M...>
191template<
typename R,
typename ...ARGS>
192struct Svr_arg_pack<R (ARGS...)> : Detail::Arg_pack<ARGS...>
194 using Base = Detail::Arg_pack<ARGS...>;
195 template<
typename DIR>
196 int get(
void *msg,
unsigned offset,
unsigned limit)
198 char *buf =
static_cast<char *
>(msg);
199 return Base::template get<DIR>(buf, offset, limit);
202 template<
typename DIR>
203 int set(
void *msg,
unsigned offset,
unsigned limit,
l4_ret_t ret)
205 char *buf =
static_cast<char *
>(msg);
206 return Base::template set<DIR>(buf, offset, limit, ret);
213template<
typename IPC_TYPE,
typename O,
typename ...ARGS>
217 using Pack = Svr_arg_pack<typename IPC_TYPE::rpc::ipc_type>;
220 Do_reply = IPC_TYPE::rpc::flags_type::Is_call,
232 int in_pos = Detail::Sizeof<typename IPC_TYPE::opcode_type>::size;
236 in_pos = pack.template get<Do_in_data>(&mrs->
mr[0], in_pos, in_bytes);
245 in_pos = pack.template get<Do_in_items>(&mrs->
mr[tag.
words()], 0,
251 asm volatile (
"" :
"=m" (mrs->
mr));
254 auto ret = pack.template obj_call<O,
typename IPC_TYPE::rpc, ARGS...>(o, args...);
265 int bytes = pack.template set<Do_out_data>(mrs->
mr, 0,
Mr_bytes, ret);
270 bytes = pack.template set<Do_out_items>(&mrs->
mr[words], 0,
281template<
typename RPC,
typename ...OUT_ARGS>
285 static_assert(RPC::flags_type::Is_call,
"RPC to reply to must be a call.");
304 pack.template reply<OUT_ARGS...>(L4::Types::forward<OUT_ARGS>(args)...);
307 int bytes = pack.template set<Do_out_data>(mrs->
mr, 0,
Mr_bytes, ret);
312 bytes = pack.template set<Do_out_items>(&mrs->
mr[words], 0,
335template<
typename RPC,
typename ...OUT_ARGS>
337reply(L4::Reply_cap reply_cap,
l4_ret_t res, OUT_ARGS && ...args)
340 return reply_cap.
reply(
341 L4::Ipc::Msg::pack_svr_reply<RPC, OUT_ARGS...>(
342 u, res, L4::Types::forward<OUT_ARGS>(args)...),
348template<
typename RPCS,
typename OPCODE_TYPE>
351template<
typename CLASS>
352struct Dispatch_call<L4::Typeid::Raw_ipc<CLASS>, void>
354 template<
typename OBJ,
typename ...ARGS>
356 call(OBJ *o,
l4_utcb_t *utcb, l4_msgtag_t tag, ARGS ...a)
358 return o->op_dispatch(utcb, tag, a...);
362template<
typename RPCS>
363struct Dispatch_call<RPCS, void>
365 constexpr static unsigned rmask()
366 {
return RPCS::rpc::flags_type::Rights & 3UL; }
368 template<
typename OBJ,
typename ...ARGS>
370 call(OBJ *o,
l4_utcb_t *utcb, l4_msgtag_t tag,
unsigned rights, ARGS ...a)
372 if ((rights & rmask()) != rmask())
375 using Rights = L4::Typeid::Rights<typename RPCS::rpc::class_type>;
376 return handle_svr_obj_call<RPCS>(o, utcb, tag,
377 Rights(rights), a...);
382template<
typename RPCS,
typename OPCODE_TYPE>
385 constexpr static unsigned rmask()
386 {
return RPCS::rpc::flags_type::Rights & 3UL; }
388 template<
typename OBJ,
typename ...ARGS>
390 _call(OBJ *o,
l4_utcb_t *utcb, l4_msgtag_t tag,
unsigned rights, OPCODE_TYPE op, ARGS ...a)
392 if (L4::Types::Same_v<typename RPCS::opcode_type, void>
393 || RPCS::Opcode == op)
395 if ((rights & rmask()) != rmask())
398 using Rights = L4::Typeid::Rights<typename RPCS::rpc::class_type>;
399 return handle_svr_obj_call<RPCS>(o, utcb, tag,
400 Rights(rights), a...);
402 return Dispatch_call<typename RPCS::next, OPCODE_TYPE>::template
403 _call<OBJ, ARGS...>(o, utcb, tag, rights, op, a...);
406 template<
typename OBJ,
typename ...ARGS>
408 call(OBJ *o,
l4_utcb_t *utcb, l4_msgtag_t tag,
unsigned rights, ARGS ...a)
412 using S = Svr_xmit<OPCODE_TYPE>;
413 l4_ret_t err = S::to_svr(
reinterpret_cast<char *
>(l4_utcb_mr_u(utcb)->mr), 0,
414 limit, op, Dir_in(), Cls_data());
418 return _call<OBJ, ARGS...>(o, utcb, tag, rights, op, a...);
423struct Dispatch_call<Typeid::Detail::Rpcs_end, void>
425 template<
typename OBJ,
typename ...ARGS>
427 _call(OBJ *,
l4_utcb_t *, l4_msgtag_t,
unsigned,
int, ARGS ...)
430 template<
typename OBJ,
typename ...ARGS>
432 call(OBJ *,
l4_utcb_t *, l4_msgtag_t,
unsigned, ARGS ...)
436template<
typename OPCODE_TYPE>
437struct Dispatch_call<Typeid::Detail::Rpcs_end, OPCODE_TYPE> :
438 Dispatch_call<Typeid::Detail::Rpcs_end, void> {};
440template<
typename RPCS,
typename OBJ,
typename ...ARGS>
442dispatch_call(OBJ *o,
l4_utcb_t *utcb, l4_msgtag_t tag,
unsigned rights, ARGS ...a)
444 return Dispatch_call<typename RPCS::type, typename RPCS::opcode_type>::template
445 call<OBJ, ARGS...>(o, utcb, tag, rights, a...);
Type information handling.
l4_ret_t reply(l4_msgtag_t tag, l4_utcb_t *utcb=l4_utcb()) noexcept
Reply with this reply capability.
@ L4_EMSGTOOLONG
Message too long.
@ L4_EMSGERRRANGE
Error code range error.
@ L4_EMSGTOOSHORT
Message too short.
l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, unsigned flags) L4_NOTHROW
Create a message tag from the specified values.
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.
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_LIKELY(x)
Expression is likely to execute.
Interface Definition Language.
l4_int16_t l4_ret_t
Return value of an IPC call as well as an RPC call.
IPC Message related functionality.
@ Item_words
number of message words for one message item
@ Mr_bytes
number of bytes available in the UTCB message registers
@ Item_bytes
number of bytes for one message item
@ Word_bytes
number of bytes for one message word
@ Mr_words
number of message words available in the UTCB
IPC related functionality.
L4 low-level kernel interface.
Server-side RPC arguments data structure used to provide arguments to the server-side implementation ...
Message tag data structure.
unsigned words() const L4_NOTHROW
Get the number of untyped words.
unsigned items() const L4_NOTHROW
Get the number of typed items.
Low-level assert implementation.
#define l4_assert(expr)
Low-level assert.
Encapsulation of the message-register block in the UTCB.
l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]
Message registers.