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 Rpc_inline_call 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 Rpc_inline_call type; enum { Opcode = (op) }; \
446  L4_INLINE_RPC_SRV_FORWARD(name); \
447  }
448 
449 #ifdef DOXYGEN
450 /**
451  * Define an inline RPC call (type and callable).
452  * \param res The result type of the RPC call
453  * \param name The name of the function (`name`_t is used for the type.)
454  * \param args The argument list of the RPC function.
455  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
456  */
457 #define L4_INLINE_RPC(res, name, args, attr...) res name args
458 #else
459 #define L4_INLINE_RPC(res, name, args...) \
460  L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
461 #endif
462 
463 #ifdef DOXYGEN
464 /**
465  * Define an inline RPC call with specific opcode (type and callable).
466  * \param op The opcode number for this function
467  * \param res The result type of the RPC call
468  * \param name The name of the function (`name`_t is used for the type.)
469  * \param args The argument list of the RPC function.
470  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
471  */
472 #define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
473 #else
474 #define L4_INLINE_RPC_OP(op, res, name, args...) \
475  L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
476 #endif
477 
478 /**
479  * Define an RPC call type (the type only, no callable).
480  * \param res The result type of the RPC call
481  * \param name The name of the function (`name`_t is used for the type.)
482  * \param args The argument list of the RPC function, and RPC attributes
483  * (L4::Ipc::Call, L4::Ipc::Call_t etc.).
484  */
485 #define L4_RPC_NF(res, name, args...) \
486  struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
487  { \
488  typedef Rpc_call type; \
489  L4_INLINE_RPC_SRV_FORWARD(name); \
490  }
491 
492 /**
493  * Define an RPC call type with specific opcode (the type only, no callable).
494  * \param op The opcode number for this function
495  * \param res The result type of the RPC call
496  * \param name The name of the function (`name`_t is used for the type.)
497  * \param args The argument list of the RPC function, and RPC attributes
498  * (L4::Ipc::Call, L4::Ipc::Call_t etc.).
499  */
500 #define L4_RPC_NF_OP(op, res, name, args...) \
501  struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
502  { \
503  typedef Rpc_call type; enum { Opcode = (op) }; \
504  L4_INLINE_RPC_SRV_FORWARD(name); \
505  }
506 
507 #ifdef DOXYGEN
508 /**
509  * Define an RPC call (type and callable).
510  * \param res The result type of the RPC call
511  * \param name The name of the function (`name`_t is used for the type.)
512  * \param args The argument list of the RPC function.
513  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
514  */
515 #define L4_RPC(res, name, args, attr...) res name args
516 #else
517 #define L4_RPC(res, name, args...) \
518  L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
519 #endif
520 
521 #ifdef DOXYGEN
522 /**
523  * Define an RPC call with specific opcode (type and callable).
524  * \param op The opcode number for this function
525  * \param res The result type of the RPC call
526  * \param name The name of the function (`name`_t is used for the type.)
527  * \param args The argument list of the RPC function.
528  * \param attr Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
529  */
530 #define L4_RPC_OP(op, res, name, args, attr...) res name args
531 #else
532 #define L4_RPC_OP(op, res, name, args...) \
533  L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
534 #endif
535 
536 
537 /**
538  * \internal
539  * Implementation details
540  */
541 namespace Detail {
542 
543 /**
544  * \tparam ARGS The list of arguments used for the RPC function.
545  */
546 template<typename ...ARGS>
547 struct Buf
548 {
549 public:
550  template<typename DIR>
551  static int write(char *, int offset, int)
552  { return offset; }
553 
554  template<typename DIR>
555  static int read(char *, int offset, int, long)
556  { return offset; }
557 
558  typedef void Base;
559 };
560 
561 template<typename A, typename ...M>
562 struct Buf<A, M...> : Buf<M...>
563 {
564  typedef Buf<M...> Base;
565 
566  typedef Clnt_xmit<A> xmit;
567  typedef typename _Elem<A>::arg_type arg_type;
568  typedef Detail::_Plain<arg_type> plain;
569 
570  template<typename DIR>
571  static int
572  write(char *base, int offset, int limit,
573  arg_type a, typename _Elem<M>::arg_type ...m)
574  {
575  offset = xmit::to_msg(base, offset, limit, plain::deref(a),
576  typename DIR::dir(), typename DIR::cls());
577  return Base::template write<DIR>(base, offset, limit, m...);
578  }
579 
580  template<typename DIR>
581  static int
582  read(char *base, int offset, int limit, long ret,
583  arg_type a, typename _Elem<M>::arg_type ...m)
584  {
585  int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
586  typename DIR::dir(), typename DIR::cls());
587  if (L4_LIKELY(r >= 0))
588  return Base::template read<DIR>(base, r, limit, ret, m...);
589 
590  if (_Elem<A>::Is_optional)
591  return Base::template read<DIR>(base, offset, limit, ret, m...);
592 
593  return r;
594  }
595 };
596 
597 template <typename ...ARGS> struct _Part
598 {
599  /// The buffer type with op-code.
600  typedef Buf<ARGS...> Data;
601 
602  template<typename DIR>
603  static int write(void *b, int offset, int limit,
604  typename _Elem<ARGS>::arg_type ...m)
605  {
606  int r = Data::template write<DIR>((char *)b, offset, limit, m...);
607  if (L4_LIKELY(r >= offset))
608  return r - offset;
609  return r;
610  }
611 
612  template<typename DIR>
613  static int read(void *b, int offset, int limit, long ret,
614  typename _Elem<ARGS>::arg_type ...m)
615  {
616  int r = Data::template read<DIR>((char *)b, offset, limit, ret, m...);
617  if (L4_LIKELY(r >= offset))
618  return r - offset;
619  return r;
620  }
621 };
622 
623 /**
624  * template declaration for message parts in message registers
625  * \tparam IPC_TYPE The function signature intended for marshalling
626  * \tparam OPCODE The opcode data type for the messages (use void for
627  * protocols without opcodes)
628  */
629 template<typename IPC_TYPE, typename OPCODE = void>
630 struct Part;
631 
632 // The version without an op-code
633 template<typename R, typename ...ARGS>
634 struct Part<R (ARGS...), void> : _Part<ARGS...>
635 {
636  /// The buffer type with op-code.
637  typedef Buf<ARGS...> Data;
638 
639  // write arguments, skipping the dummy opcode
640  template<typename DIR>
641  static int write_op(void *b, int offset, int limit,
642  int /*placeholder for op*/,
643  typename _Elem<ARGS>::arg_type ...m)
644  {
645  int r = Data::template write<DIR>((char *)b, offset, limit, m...);
646  if (L4_LIKELY(r >= offset))
647  return r - offset;
648  return r;
649  }
650 };
651 
652 // Message part with additional opcode
653 template<typename OPCODE, typename R, typename ...ARGS>
654 struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
655 {
656  typedef OPCODE opcode_type;
657  /// The buffer type with op-code.
658  typedef Buf<opcode_type, ARGS...> Data;
659 
660  // write arguments, including the opcode
661  template<typename DIR>
662  static int write_op(void *b, int offset, int limit,
663  opcode_type op, typename _Elem<ARGS>::arg_type ...m)
664  {
665  int r = Data::template write<DIR>((char *)b, offset, limit, op, m...);
666  if (L4_LIKELY(r >= offset))
667  return r - offset;
668  return r;
669  }
670 };
671 
672 
673 } // namespace Detail
674 
675 //----------------------------------------------------
676 // Implementation of the RPC call
677 // TODO: Add support for timeout via special RPC argument
678 // TODO: Add support for passing the UTCB pointer as argument
679 //
680 template<typename OP, typename CLASS, typename FLAGS, typename R,
681  typename ...ARGS>
682 inline R
683 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
684  call(L4::Cap<CLASS> cap,
685  typename _Elem<ARGS>::arg_type ...a,
686  l4_utcb_t *utcb) throw()
687 {
688  using namespace Ipc::Msg;
689 
690  typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
691  typedef typename Rpcs::template Rpc<OP> Opt;
692  typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
693 
694  l4_msg_regs_t *mrs = l4_utcb_mr_u(utcb);
695 
696  // handle in-data part of the arguments
697  int send_bytes =
698  Args::template write_op<Do_in_data>(mrs->mr, 0, Mr_bytes,
699  Opt::Opcode, a...);
700 
701  if (L4_UNLIKELY(send_bytes < 0))
702  return return_err<R>(send_bytes);
703 
704  send_bytes = align_to<l4_umword_t>(send_bytes);
705  int const send_words = send_bytes / Word_bytes;
706  // write the in-items part of the message if there is one
707  int item_bytes =
708  Args::template write<Do_in_items>(&mrs->mr[send_words], 0,
709  Mr_bytes - send_bytes, a...);
710 
711  if (L4_UNLIKELY(item_bytes < 0))
712  return return_err<R>(item_bytes);
713 
714  int send_items = item_bytes / Item_bytes;
715 
716  {
717  // setup the receive buffers for the RPC call
718  l4_buf_regs_t *brs = l4_utcb_br_u(utcb);
719  // XXX: we currently support only one type of receive buffers per call
720  brs->bdr = 0; // we always start at br[0]
721 
722  // the limit leaves us at least one register for the zero terminator
723  // add the buffers given as arguments to the buffer registers
724  int bytes =
725  Args::template write<Do_rcv_buffers>(brs->br, 0, Br_bytes - Word_bytes,
726  a...);
727 
728  if (L4_UNLIKELY(bytes < 0))
729  return return_err<R>(bytes);
730 
731  brs->br[bytes / Word_bytes] = 0;
732  }
733 
734 
735  // here we do the actual IPC ---------------------------------
736  l4_msgtag_t t;
737  t = l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
738  // do the call (Q: do we need support for timeouts?)
739  if (flags_type::Is_call)
740  t = l4_ipc_call(cap.cap(), utcb, t, flags_type::timeout());
741  else
742  {
743  t = l4_ipc_send(cap.cap(), utcb, t, flags_type::timeout());
744  if (L4_UNLIKELY(t.has_error()))
745  return return_ipc_err<R>(t, utcb);
746 
747  return return_code<R>(l4_msgtag(0, 0, 0, t.flags()));
748  }
749 
750  // unmarshalling starts here ---------------------------------
751 
752  // bail out early in the case of an IPC error
753  if (L4_UNLIKELY(t.has_error()))
754  return return_ipc_err<R>(t, utcb);
755 
756  // take the label as return value
757  long r = t.label();
758 
759  // bail out on negative error codes too
760  if (L4_UNLIKELY(r < 0))
761  return return_err<R>(r);
762 
763  int const rcv_bytes = t.words() * Word_bytes;
764 
765  // read the static out-data values to the arguments
766  int err = Args::template read<Do_out_data>(mrs->mr, 0, rcv_bytes, r, a...);
767 
768  int const item_limit = t.items() * Item_bytes;
769 
770  if (L4_UNLIKELY(err < 0 || item_limit > Mr_bytes))
771  return return_err<R>(-L4_EMSGTOOSHORT);
772 
773  // read the static out-items to the arguments
774  err = Args::template read<Do_out_items>(&mrs->mr[t.words()], 0, item_limit,
775  r, a...);
776 
777  if (L4_UNLIKELY(err < 0))
778  return return_err<R>(-L4_EMSGTOOSHORT);
779 
780  return return_code<R>(t);
781 }
782 
783 } // namespace Msg
784 } // namesapce Ipc
785 } // namespace L4
786 
787