L4Re - L4 Runtime Environment
ipc_iface
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  *
9  * As a special exception, you may use this file as part of a free software
10  * library without restriction. Specifically, if other files instantiate
11  * templates or use macros or inline functions from this file, or you compile
12  * this file and link it with other files to produce an executable, this
13  * file does not by itself cause the resulting executable to be covered by
14  * the GNU General Public License. This exception does not however
15  * invalidate any other reasons why the executable file might be covered by
16  * the GNU General Public License.
17  */
18 #pragma once
19 #pragma GCC system_header
20 
21 #include <l4/sys/cxx/ipc_basics>
22 #include <l4/sys/cxx/ipc_types>
23 #include <l4/sys/__typeinfo.h>
24 
25 /**
26  * \file l4/sys/cxx/ipc_iface Interface Definition Language
27  * \sa L4_RPC, L4_INLINE_RPC, L4::Ipc::Call L4::Ipc::Send_only,
28  * L4::Ipc::Msg::Rpc_call, L4::Ipc::Msg::Rpc_inline_call
29  *
30  *
31  */
32 
33 /**
34  * \page l4_cxx_ipc_iface Interface Definition Language
35  *
36  * An interface definition in L4Re is normally declared as a class
37  * derived from L4::Kobject_t. For example, the simple calculator
38  * example declares its interface like that:
39  *
40  * ~~~{.cpp}
41  * struct Calc : L4::Kobject_t<Calc, L4::Kobject>
42  * {
43  * L4_INLINE_RPC(int, sub, (l4_uint32_t a, l4_uint32_t b, l4_uint32_t *res));
44  * L4_INLINE_RPC(int, neg, (l4_uint32_t a, l4_uint32_t *res));
45  *
46  * typedef L4::Typeid::Rpcs<sub_t, neg_t> Rpcs;
47  * };
48  * ~~~
49  *
50  *
51  * The signature of each function is first declared using on of the RPC
52  * macros (see below) and then all the functions need to be listed in the
53  * Rpcs type.
54  *
55  * \section l4_cxx_ipc_iface_types Parameter types for RPC
56  *
57  * Generally all value parameters, const reference parameters,
58  * and const pointer parameters to an RPC interface are considered as input
59  * parameters for the RPC and are transmitted from the client to the server.
60  * \note This means that `char const *` is treated as an input `char` and not
61  * as a zero terminated string value, for strings see L4::Ipc::String<>.
62  *
63  * Parameters that are non-const references or non-const pointers are treated
64  * as output parameters going from the server to the client.
65  *
66  * ~~~~~~{.cpp}
67  * L4_RPC(long, test, (int arg1, char const *arg2, unsigned *ret1));
68  * ~~~~~~
69  *
70  * The example shows the declaration of a method called `test` with `long`
71  * as return type, `arg1` is an `int` input, `arg2` a `char` input, and
72  * `ret1` an `unsigned` output parameter.
73  *
74  * | Type | Direction | Client-Type | Server-Type |
75  * |:---------------------------------|:----------|:------------------|:-----------------------|
76  * | `T` | Input | `T` | `T` |
77  * | `T const &` | Input | `T const &` | `T const &` |
78  * | `T const *` | Input | `T const *` | `T const &` |
79  * | `T &` | Output | `T &` | `T &` |
80  * | `T *` | Output | `T *` | `T &` |
81  * | `L4::Ipc::In_out<T &>` | In/Out | `T &` | `T &` |
82  * | `L4::Ipc::In_out<T *>` | In/Out | `T *` | `T &` |
83  * | `L4::Ipc::Cap<T>` | Input | `L4::Ipc::Cap<T>` | `L4::Ipc::Snd_fpage` |
84  * | `L4::Ipc::Out<L4::Cap<T> >` | Output | `L4::Cap<T>` | `L4::Ipc::Cap<T> &` |
85  *
86  * Array types can be used to transmit arrays of variable length. They can
87  * either be stored in a client-provided buffer (L4::Ipc::Array), copied into
88  * a server-provided buffer (L4::Ipc::Array_in_buf) or directly read and written
89  * into the UTCB (L4::Ipc::Array_ref). For latter type, the start
90  * position of an array type needs to be known in advance. That implies that
91  * only one such array can be transmitted per direction and it must be the
92  * last part in the message.
93  *
94  * | Type | Direction | Client-Type | Server-Type |
95  * |:--------------------------|:----------|:--------------------------|:----------------------------------|
96  * | `L4::Ipc::Array<const T>` | Input | `L4::Ipc::Array<const T>` | `L4::Ipc::Array_ref<const T>` |
97  * | `L4::Ipc::Array<const T>` | Input | `L4::Ipc::Array<const T>` | `L4::Ipc::Array_in_buf<T> const &`|
98  * | `L4::Ipc::Array<T> &` | Output | `L4::Ipc::Array<T> &` | `L4::Ipc::Array_ref<T> &` |
99  * | `L4::Ipc::Array_ref<T> &` | Output | `L4::Ipc::Array_ref<T> &` | `L4::Ipc::Array_ref<T> &` |
100  *
101  *
102  * Finally, there are some optional types where the sender can choose
103  * if the parameter should be included in the message. These types are for
104  * the implementation of some legacy message formats and should generally
105  * not be needed for the definition of ordinary interfaces.
106  *
107  * | Type | Direction | Client-Type | Server-Type |
108  * |:-------------------------------|:----------|:-------------------------|:-------------------------------|
109  * | `L4::Ipc::Opt<T>` | Input | `L4::Ipc::Opt<T>` | `T` |
110  * | `L4::Ipc::Opt<const T*>` | Input | `L4::Ipc::Opt<const T*>` | `T` |
111  * | `L4::Ipc::Opt<T &>` | Output | `T &` | `L4::Ipc::Opt<T> &` |
112  * | `L4::Ipc::Opt<T *>` | Output | `T *` | `L4::Ipc::Opt<T> &` |
113  * | `L4::Ipc::Opt<Array_ref<T> &>` | Output | `Array_ref<T> &` | `L4::Ipc::Opt<Array_ref<T>> &` |
114  *
115  * \section l4_cxx_ipc_iface_return_types RPC Return Types
116  *
117  * On the server side, the return type of an RPC handling function is always
118  * `long`. The return value is transmitted via the label field in l4_msgtag_t
119  * and is therefore restricted to its length. Per convention, a negative
120  * return value is interpreted as an error condition. If the return value
121  * is negative, output parameters are not transmitted back to the client.
122  *
123  * \attention The client must never rely on the content of output parameters
124  * when the return value is negative.
125  *
126  * On the client-side, the return value of the RPC is set as defined in
127  * the RPC macro. If `l4_msgtag_t` is given, then the client has access
128  * to the full message tag, otherwise the return type should be `long`.
129  * Note that the client might not only receive the server return value in
130  * response but also an IPC error code.
131  *
132  * \section l4_cxx_ipc_iface_members RPC Method Declaration
133  *
134  * RPC member functions can be declared using one of the following C++ macros.
135  *
136  * For inline RPC stubs, where the RPC stub code itself is `inline`:
137  * *
138  * ~~~{.cpp}
139  * L4_INLINE_RPC(res, name, (args...), flags)
140  * ~~~
141  * \copybrief #L4_INLINE_RPC
142  * *
143  * ~~~{.cpp}
144  * L4_INLINE_RPC_OP(op, res, name, (args...), flags)
145  * ~~~
146  * \copybrief #L4_INLINE_RPC_OP
147  * *
148  * ~~~{.cpp}
149  * L4_INLINE_RPC_NF(res, name, (args...), flags)
150  * ~~~
151  * \copybrief #L4_INLINE_RPC_NF
152  * *
153  * ~~~{.cpp}
154  * L4_INLINE_RPC_NF_OP(opcode, Ret_type, func_name, (args...), flags)
155  * ~~~
156  * \copybrief #L4_INLINE_RPC_NF_OP
157  *
158  * For external RPC stubs, where the RPC stub code must be defined in a
159  * separate compile unit (usually a `.cc` file):
160  * *
161  * ~~~{.cpp}
162  * L4_RPC(Ret_type, func_name, (args...), flags)
163  * ~~~
164  * \copybrief #L4_RPC
165  *
166  * *
167  * ~~~{.cpp}
168  * L4_RPC_OP(opcode, Ret_type, func_name, (args...), flags)
169  * ~~~
170  * \copybrief #L4_RPC_OP
171  * *
172  * ~~~{.cpp}
173  * L4_RPC_NF(Ret_type, func_name, (args...), flags)
174  * ~~~
175  * \copybrief #L4_RPC_NF
176  * *
177  * ~~~{.cpp}
178  * L4_RPC_NF_OP(opcode, Ret_type, func_name, (args...), flags)
179  * ~~~
180  * \copybrief #L4_RPC_NF_OP
181  *
182  * To generate the implementation of an external RPC stub:
183  * *
184  * ~~~{.cpp}
185  * L4_RPC_DEF(class_name::func_name)
186  * ~~~
187  * \copybrief #L4_RPC_DEF
188  *
189  * The `NF` versions of the macro generally do not generate a callable
190  * member function named `<name>` but do only generate the type `<name>_t`.
191  * This data type can be used to call the RPC stub explicitly using
192  * `<name>_t::call(L4::Cap<Iface_class> cap, args...)`.
193  *
194  */
195 
196 // TODO: add some more documentation
197 namespace L4 { namespace Ipc {
198 
199 /**
200  * RPC attribute for a standard RPC call.
201  *
202  * This is the default for the \a FLAGS parameter for L4::Ipc::Msg::Rpc_call
203  * L4::Ipc::Msg::Rpc_inline_call templates and declares the RPC to have default
204  * call semantics and timeouts.
205  *
206  * Examples:
207  * ~~~~~~~~~~~{.cpp}
208  * L4_RPC(long, send, (unsigned value), L4::Ipc::Call);
209  * ~~~~~~~~~~~
210  * which is equvalent to:
211  * ~~~~~~~~~~~{.cpp}
212  * L4_RPC(long, send, (unsigned value));
213  * ~~~~~~~~~~~
214  */
215 struct L4_EXPORT Call
216 {
217  enum { Is_call = true };
218  enum { Rights = 0 };
219  static l4_timeout_t timeout() { return L4_IPC_NEVER; }
220 };
221 
222 /**
223  * RPC attribute for an RPC call, with zero send timeout.
224  */
225 struct L4_EXPORT Call_zero_send_timeout : Call
226 {
227  static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; }
228 };
229 
230 /**
231  * RPC attribute for an RPC call with required rights.
232  * \tparam RIGHTS The capability rights required for this call.
233  * #L4_CAP_FPAGE_W and #L4_CAP_FPAGE_S are checked within the
234  * server (and -#L4_EPERM shall be returned if the caller has
235  * insufficient rights). #L4_CAP_FPAGE_R is always on but
236  * might be specified for documentation purposes. Other rights
237  * cannot be used in this context, because they cannot be
238  * checked at the server side.
239  *
240  * Examples:
241  * ~~~~~~~~~~~{.cpp}
242  * L4_RPC(long, func, (unsigned value), L4::Ipc::Call_t<L4_CAP_FPAGE_RW>);
243  * ~~~~~~~~~~~
244  */
245 template<unsigned RIGHTS>
246 struct L4_EXPORT Call_t : Call
247 {
248  enum { Rights = RIGHTS };
249 };
250 
251 /**
252  * RPC attribute for a send-only RPC.
253  *
254  * This class can be used as FLAGS parameter to L4::Ipc::Msg::Rpc_call and
255  * L4::Ipc::Msg::Rpc_inline_call templates and declares the RPC to use send-only
256  * semantics and timeouts.
257  *
258  * Examples:
259  * ~~~~~~~~~~~{.cpp}
260  * L4_RPC(long, send, (unsigned value), L4::Ipc::Send_only);
261  * ~~~~~~~~~~~
262  */
263 struct L4_EXPORT Send_only
264 {
265  enum { Is_call = false };
266  enum { Rights = 0 };
267  static l4_timeout_t timeout() { return L4_IPC_NEVER; }
268 };
269 
270 namespace Msg {
271 
272 /**
273  * \internal
274  * Callable data type for the given RPC signature \a SIG.
275  * \tparam OP The type for the specific operation, usually this type
276  * inherits from Rpc_call<>.
277  * \tparam CLASS The class that contains this callable. The class is
278  * used to determine the protocol ID for the IPC and
279  * \a CLASS plus \a OP are used to determine the op-code.
280  * \tparam SIG The function signature for the RPC.
281  */
282 template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
283 struct L4_EXPORT Rpc_inline_call;
284 
285 /**
286  * \internal
287  * The implementation for SIG == R (ARGS...)
288  */
289 template<typename OP, typename CLASS, typename FLAGS, typename R,
290  typename ...ARGS>
291 struct L4_EXPORT Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
292 {
293  template<typename T> struct Result { typedef T result_type; };
294  enum
295  {
296  Return_tag = L4::Types::Same<R, l4_msgtag_t>::value
297  };
298 
299  /// Our type
300  typedef Rpc_inline_call type;
301  /// The type used to uniquely identify the operation
302  typedef OP op_type;
303  /// The class that contains this operation
304  typedef CLASS class_type;
305  /// The result type of the callable
306  typedef typename Result<R>::result_type result_type;
307  /// The original signature given to Rpc_call
308  typedef R ipc_type (ARGS...);
309  /// The signature of the client callable
310  typedef result_type func_type (typename _Elem<ARGS>::arg_type...);
311 
312  /// The RPC flags type (specifying e.g. send-only or call operation)
313  typedef FLAGS flags_type;
314 
315  template<typename RES>
316  static typename L4::Types::Enable_if< Return_tag, RES >::type
317  return_err(long err) { return l4_msgtag(err, 0, 0, 0); }
318 
319  template<typename RES>
320  static typename L4::Types::Enable_if< Return_tag, RES >::type
321  return_ipc_err(l4_msgtag_t tag, l4_utcb_t const *) { return tag; }
322 
323  template<typename RES>
324  static typename L4::Types::Enable_if< Return_tag, RES >::type
325  return_code(l4_msgtag_t tag) { return tag; }
326 
327  template<typename RES>
328  static typename L4::Types::Enable_if< !Return_tag, RES >::type
329  return_err(long err) { return err; }
330 
331  template<typename RES>
332  static typename L4::Types::Enable_if< !Return_tag, RES >::type
333  return_ipc_err(l4_msgtag_t, l4_utcb_t *utcb)
334  { return l4_ipc_to_errno(l4_ipc_error_code(utcb)); }
335 
336  template<typename RES>
337  static typename L4::Types::Enable_if< !Return_tag, RES >::type
338  return_code(l4_msgtag_t tag) { return tag.label(); }
339 
340  static R call(L4::Cap<class_type> cap,
341  typename _Elem<ARGS>::arg_type ...a,
342  l4_utcb_t *utcb = l4_utcb()) throw();
343 };
344 
345 /**
346  * \internal
347  * non-inline version of Rpc_call
348  */
349 template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
350 struct L4_EXPORT Rpc_call;
351 
352 /**
353  * \internal
354  * Helper to define a callable member of an RPC interface.
355  *
356  * \tparam IPC Some type derived from Rpc_call or Rpc_inline_call
357  * \tparam SIG signature of the method
358  */
359 template<typename IPC, typename SIG> struct _Call;
360 
361 /// \internal
362 template<typename IPC, typename R, typename ...ARGS>
363 struct _Call<IPC, R (ARGS...)>
364 {
365 public:
366  typedef typename IPC::class_type class_type;
367  typedef typename IPC::result_type result_type;
368 
369 private:
370  L4::Cap<class_type> cap() const
371  {
372  return L4::Cap<class_type>(reinterpret_cast<l4_cap_idx_t>(this)
373  & L4_CAP_MASK);
374  }
375 
376 public:
377  /// The implementation of this callable
378  result_type operator () (ARGS ...a, l4_utcb_t *utcb = l4_utcb()) const throw()
379  { return IPC::call(cap(), a..., utcb); }
380 };
381 
382 /**
383  * \internal
384  * Helper to define a callable member of an RPC interface.
385  * \tparam IPC The type defining the RPC method, usually derived from
386  * Rpc_inline_call.
387  */
388 template<typename IPC> struct Call : _Call<IPC, typename IPC::func_type> {};
389 
390 /**
391  * \internal
392  * non-inline version of Rpc_call (for SIG == R (ARGS...))
393  */
394 template<typename OP,
395  typename CLASS,
396  typename FLAGS,
397  typename R,
398  typename ...ARGS>
399 struct L4_EXPORT Rpc_call<OP, CLASS, R (ARGS...), FLAGS> :
400  Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
401 {
402  static R call(L4::Cap<CLASS> cap,
403  typename _Elem<ARGS>::arg_type ...a,
404  l4_utcb_t *utcb = l4_utcb()) throw();
405 };
406 
407 #define L4_INLINE_RPC_SRV_FORWARD(name) \
408  template<typename OBJ> struct fwd \
409  { \
410  OBJ *o; \
411  fwd(OBJ *o) : o(o) {} \
412  template<typename ...ARGS> long call(ARGS ...a) \
413  { return o->op_##name(a...); } \
414  }
415 
416 
417 /**
418  * Define an inline RPC call type (the type only, no callable).
419  * \param res The result type of the RPC call
420  * \param name The name of the function (`name`_t is used for the type.)
421  * \param args The argument list of the RPC function, and RPC attributes
422  * (L4::Ipc::Call, L4::Ipc::Call_t etc.).
423  *
424  * Stubs generated by this macro can be used explicitly in custom wrapper
425  * methods that need to use the underlying RPC code and provide some higher
426  * level abstraction, for example with default arguments or extra argument
427  * conversion.
428  */
429 #define L4_INLINE_RPC_NF(res, name, args...) \
430  struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
431  { \
432  typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
433  L4_INLINE_RPC_SRV_FORWARD(name); \
434  }
435 
436 /**
437  * \brief Define an inline RPC call type with specific opcode (the type only,
438  * no callable).
439  * \param op The opcode number for this function
440  * \copydetails #L4_INLINE_RPC_NF
441  */
442 #define L4_INLINE_RPC_NF_OP(op, res, name, args...) \
443  struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
444  { \
445  typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
446  enum { Opcode = (op) }; \
447  L4_INLINE_RPC_SRV_FORWARD(name); \
448  }
449 
450 #ifdef DOXYGEN
451 /**
452  * Define an inline RPC call (type and callable).
453  * \param res The result type of the RPC call
454  * \param name The name of the function (`name`_t is used for the type.)
455  * \param args The argument list of the RPC function.
456  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
457  */
458 #define L4_INLINE_RPC(res, name, args, attr...) res name args
459 #else
460 #define L4_INLINE_RPC(res, name, args...) \
461  L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
462 #endif
463 
464 #ifdef DOXYGEN
465 /**
466  * Define an inline RPC call with specific opcode (type and callable).
467  * \param op The opcode number for this function
468  * \param res The result type of the RPC call
469  * \param name The name of the function (`name`_t is used for the type.)
470  * \param args The argument list of the RPC function.
471  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
472  */
473 #define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
474 #else
475 #define L4_INLINE_RPC_OP(op, res, name, args...) \
476  L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
477 #endif
478 
479 /**
480  * Define an RPC call type (the type only, no callable).
481  * \param res The result type of the RPC call
482  * \param name The name of the function (`name`_t is used for the type.)
483  * \param args The argument list of the RPC function, and RPC attributes
484  * (L4::Ipc::Call, L4::Ipc::Call_t etc.).
485  */
486 #define L4_RPC_NF(res, name, args...) \
487  struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
488  { \
489  typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
490  L4_INLINE_RPC_SRV_FORWARD(name); \
491  }
492 
493 /**
494  * Define an RPC call type with specific opcode (the type only, no callable).
495  * \param op The opcode number for this function
496  * \param res The result type of the RPC call
497  * \param name The name of the function (`name`_t is used for the type.)
498  * \param args The argument list of the RPC function, and RPC attributes
499  * (L4::Ipc::Call, L4::Ipc::Call_t etc.).
500  */
501 #define L4_RPC_NF_OP(op, res, name, args...) \
502  struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
503  { \
504  typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
505  enum { Opcode = (op) }; \
506  L4_INLINE_RPC_SRV_FORWARD(name); \
507  }
508 
509 #ifdef DOXYGEN
510 /**
511  * Define an RPC call (type and callable).
512  * \param res The result type of the RPC call
513  * \param name The name of the function (`name`_t is used for the type.)
514  * \param args The argument list of the RPC function.
515  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
516  */
517 #define L4_RPC(res, name, args, attr...) res name args
518 #else
519 #define L4_RPC(res, name, args...) \
520  L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
521 #endif
522 
523 #ifdef DOXYGEN
524 /**
525  * Define an RPC call with specific opcode (type and callable).
526  * \param op The opcode number for this function
527  * \param res The result type of the RPC call
528  * \param name The name of the function (`name`_t is used for the type.)
529  * \param args The argument list of the RPC function.
530  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
531  */
532 #define L4_RPC_OP(op, res, name, args, attr...) res name args
533 #else
534 #define L4_RPC_OP(op, res, name, args...) \
535  L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
536 #endif
537 
538 
539 /**
540  * \internal
541  * Implementation details
542  */
543 namespace Detail {
544 
545 /**
546  * \tparam ARGS The list of arguments used for the RPC function.
547  */
548 template<typename ...ARGS>
549 struct Buf
550 {
551 public:
552  template<typename DIR>
553  static int write(char *, int offset, int)
554  { return offset; }
555 
556  template<typename DIR>
557  static int read(char *, int offset, int, long)
558  { return offset; }
559 
560  typedef void Base;
561 };
562 
563 template<typename A, typename ...M>
564 struct Buf<A, M...> : Buf<M...>
565 {
566  typedef Buf<M...> Base;
567 
568  typedef Clnt_xmit<A> xmit;
569  typedef typename _Elem<A>::arg_type arg_type;
570  typedef Detail::_Plain<arg_type> plain;
571 
572  template<typename DIR>
573  static int
574  write(char *base, int offset, int limit,
575  arg_type a, typename _Elem<M>::arg_type ...m)
576  {
577  offset = xmit::to_msg(base, offset, limit, plain::deref(a),
578  typename DIR::dir(), typename DIR::cls());
579  return Base::template write<DIR>(base, offset, limit, m...);
580  }
581 
582  template<typename DIR>
583  static int
584  read(char *base, int offset, int limit, long ret,
585  arg_type a, typename _Elem<M>::arg_type ...m)
586  {
587  int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
588  typename DIR::dir(), typename DIR::cls());
589  if (L4_LIKELY(r >= 0))
590  return Base::template read<DIR>(base, r, limit, ret, m...);
591 
592  if (_Elem<A>::Is_optional)
593  return Base::template read<DIR>(base, offset, limit, ret, m...);
594 
595  return r;
596  }
597 };
598 
599 template <typename ...ARGS> struct _Part
600 {
601  /// The buffer type with op-code.
602  typedef Buf<ARGS...> Data;
603 
604  template<typename DIR>
605  static int write(void *b, int offset, int limit,
606  typename _Elem<ARGS>::arg_type ...m)
607  {
608  int r = Data::template write<DIR>((char *)b, offset, limit, m...);
609  if (L4_LIKELY(r >= offset))
610  return r - offset;
611  return r;
612  }
613 
614  template<typename DIR>
615  static int read(void *b, int offset, int limit, long ret,
616  typename _Elem<ARGS>::arg_type ...m)
617  {
618  int r = Data::template read<DIR>((char *)b, offset, limit, ret, m...);
619  if (L4_LIKELY(r >= offset))
620  return r - offset;
621  return r;
622  }
623 };
624 
625 /**
626  * template declaration for message parts in message registers
627  * \tparam IPC_TYPE The function signature intended for marshalling
628  * \tparam OPCODE The opcode data type for the messages (use void for
629  * protocols without opcodes)
630  */
631 template<typename IPC_TYPE, typename OPCODE = void>
632 struct Part;
633 
634 // The version without an op-code
635 template<typename R, typename ...ARGS>
636 struct Part<R (ARGS...), void> : _Part<ARGS...>
637 {
638  /// The buffer type with op-code.
639  typedef Buf<ARGS...> Data;
640 
641  // write arguments, skipping the dummy opcode
642  template<typename DIR>
643  static int write_op(void *b, int offset, int limit,
644  int /*placeholder for op*/,
645  typename _Elem<ARGS>::arg_type ...m)
646  {
647  int r = Data::template write<DIR>((char *)b, offset, limit, m...);
648  if (L4_LIKELY(r >= offset))
649  return r - offset;
650  return r;
651  }
652 };
653 
654 // Message part with additional opcode
655 template<typename OPCODE, typename R, typename ...ARGS>
656 struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
657 {
658  typedef OPCODE opcode_type;
659  /// The buffer type with op-code.
660  typedef Buf<opcode_type, ARGS...> Data;
661 
662  // write arguments, including the opcode
663  template<typename DIR>
664  static int write_op(void *b, int offset, int limit,
665  opcode_type op, typename _Elem<ARGS>::arg_type ...m)
666  {
667  int r = Data::template write<DIR>((char *)b, offset, limit, op, m...);
668  if (L4_LIKELY(r >= offset))
669  return r - offset;
670  return r;
671  }
672 };
673 
674 
675 } // namespace Detail
676 
677 //----------------------------------------------------
678 // Implementation of the RPC call
679 // TODO: Add support for timeout via special RPC argument
680 // TODO: Add support for passing the UTCB pointer as argument
681 //
682 template<typename OP, typename CLASS, typename FLAGS, typename R,
683  typename ...ARGS>
684 inline R
685 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
686  call(L4::Cap<CLASS> cap,
687  typename _Elem<ARGS>::arg_type ...a,
688  l4_utcb_t *utcb) throw()
689 {
690  using namespace Ipc::Msg;
691 
692  typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
693  typedef typename Rpcs::template Rpc<OP> Opt;
694  typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
695 
696  l4_msg_regs_t *mrs = l4_utcb_mr_u(utcb);
697 
698  // handle in-data part of the arguments
699  int send_bytes =
700  Args::template write_op<Do_in_data>(mrs->mr, 0, Mr_bytes,
701  Opt::Opcode, a...);
702 
703  if (L4_UNLIKELY(send_bytes < 0))
704  return return_err<R>(send_bytes);
705 
706  send_bytes = align_to<l4_umword_t>(send_bytes);
707  int const send_words = send_bytes / Word_bytes;
708  // write the in-items part of the message if there is one
709  int item_bytes =
710  Args::template write<Do_in_items>(&mrs->mr[send_words], 0,
711  Mr_bytes - send_bytes, a...);
712 
713  if (L4_UNLIKELY(item_bytes < 0))
714  return return_err<R>(item_bytes);
715 
716  int send_items = item_bytes / Item_bytes;
717 
718  {
719  // setup the receive buffers for the RPC call
720  l4_buf_regs_t *brs = l4_utcb_br_u(utcb);
721  // XXX: we currently support only one type of receive buffers per call
722  brs->bdr = 0; // we always start at br[0]
723 
724  // the limit leaves us at least one register for the zero terminator
725  // add the buffers given as arguments to the buffer registers
726  int bytes =
727  Args::template write<Do_rcv_buffers>(brs->br, 0, Br_bytes - Word_bytes,
728  a...);
729 
730  if (L4_UNLIKELY(bytes < 0))
731  return return_err<R>(bytes);
732 
733  brs->br[bytes / Word_bytes] = 0;
734  }
735 
736 
737  // here we do the actual IPC ---------------------------------
738  l4_msgtag_t t;
739  t = l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
740  // do the call (Q: do we need support for timeouts?)
741  if (flags_type::Is_call)
742  t = l4_ipc_call(cap.cap(), utcb, t, flags_type::timeout());
743  else
744  {
745  t = l4_ipc_send(cap.cap(), utcb, t, flags_type::timeout());
746  if (L4_UNLIKELY(t.has_error()))
747  return return_ipc_err<R>(t, utcb);
748 
749  return return_code<R>(l4_msgtag(0, 0, 0, t.flags()));
750  }
751 
752  // unmarshalling starts here ---------------------------------
753 
754  // bail out early in the case of an IPC error
755  if (L4_UNLIKELY(t.has_error()))
756  return return_ipc_err<R>(t, utcb);
757 
758  // take the label as return value
759  long r = t.label();
760 
761  // bail out on negative error codes too
762  if (L4_UNLIKELY(r < 0))
763  return return_err<R>(r);
764 
765  int const rcv_bytes = t.words() * Word_bytes;
766 
767  // read the static out-data values to the arguments
768  int err = Args::template read<Do_out_data>(mrs->mr, 0, rcv_bytes, r, a...);
769 
770  int const item_limit = t.items() * Item_bytes;
771 
772  if (L4_UNLIKELY(err < 0 || item_limit > Mr_bytes))
773  return return_err<R>(-L4_EMSGTOOSHORT);
774 
775  // read the static out-items to the arguments
776  err = Args::template read<Do_out_items>(&mrs->mr[t.words()], 0, item_limit,
777  r, a...);
778 
779  if (L4_UNLIKELY(err < 0))
780  return return_err<R>(-L4_EMSGTOOSHORT);
781 
782  return return_code<R>(t);
783 }
784 
785 } // namespace Msg
786 } // namesapce Ipc
787 } // namespace L4
788 
789