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 
196 // TODO: add some more documentation
197 namespace L4 { namespace Ipc {
198 
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 
225 struct L4_EXPORT Call_zero_send_timeout : Call
226 {
227  static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; }
228 };
229 
245 template<unsigned RIGHTS>
246 struct L4_EXPORT Call_t : Call
247 {
248  enum { Rights = RIGHTS };
249 };
250 
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 
282 template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
283 struct L4_EXPORT Rpc_inline_call;
284 
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  {
297  };
298 
300  typedef Rpc_inline_call type;
302  typedef OP op_type;
304  typedef CLASS class_type;
306  typedef typename Result<R>::result_type result_type;
308  typedef R ipc_type (ARGS...);
310  typedef result_type func_type (typename _Elem<ARGS>::arg_type...);
311 
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 
349 template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
350 struct L4_EXPORT Rpc_call;
351 
359 template<typename IPC, typename SIG> struct _Call;
360 
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:
378  result_type operator () (ARGS ...a, l4_utcb_t *utcb = l4_utcb()) const throw()
379  { return IPC::call(cap(), a..., utcb); }
380 };
381 
388 template<typename IPC> struct Call : _Call<IPC, typename IPC::func_type> {};
389 
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 
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 
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 
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 
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 
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 
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 
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 
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 
543 namespace Detail {
544 
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 {
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 
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 {
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;
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 
Encapsulation of the message-register block in the UTCB.
Definition: utcb.h:78
Compare two data types for equality.
Definition: types:189
l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]
Message registers.
Definition: utcb.h:80
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).
Definition: ipc.h:445
T read(Istream &s)
Read a value out of a stream.
Definition: ipc_stream:1394
L4 low-level kernel interface.
long l4_ipc_to_errno(unsigned long ipc_error_code) L4_NOTHROW
Get a negative error code for the given IPC error code.
Definition: ipc.h:441
unsigned long l4_cap_idx_t
L4 Capability selector Type.
Definition: types.h:342
RPC attribute for a send-only RPC.
Definition: ipc_iface:263
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition: utcb.h:67
#define L4_IPC_NEVER
never timeout
Definition: __timeout.h:80
Encapsulation of the buffer-registers block in the UTCB.
Definition: utcb.h:93
Type information handling.
Timeout pair.
Definition: __timeout.h:57
long label() const
Get the protocol value.
Definition: types.h:164
l4_umword_t bdr
Buffer descriptor.
Definition: utcb.h:96
int l4_ipc_error_code(l4_utcb_t *utcb) L4_NOTHROW
Get the error condition of the last invocation from the TCR.
Definition: ipc.h:529
int Opcode
Data type for RPC opcodes.
Definition: __typeinfo.h:47
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition: compiler.h:234
l4_cap_idx_t cap() const
Return capability selector.
Definition: capability.h:52
Mask to get only the relevant bits of an l4_cap_idx_t.
Definition: consts.h:139
RPC attribute for an RPC call, with zero send timeout.
Definition: ipc_iface:225
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
Definition: utcb.h:340
#define L4_LIKELY(x)
Expression is likely to execute.
Definition: compiler.h:233
l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, unsigned flags) L4_NOTHROW
Create a message tag from the specified values.
Definition: types.h:408
RPC attribute for an RPC call with required rights.
Definition: ipc_iface:246
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).
Definition: ipc.h:470
#define L4_IPC_SEND_TIMEOUT_0
0 send timeout
Definition: __timeout.h:82
C++ interface for capabilities.
Definition: capability.h:13
Message tag data structure.
Definition: types.h:159
Message too short.
Definition: err.h:66
RPC attribute for a standard RPC call.
Definition: ipc_iface:215
l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE]
Buffer registers.
Definition: utcb.h:99