L4Re - L4 Runtime Environment
ipc_ret_array
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 
20 #include "types"
21 #include "ipc_basics"
22 
23 namespace L4 { namespace Ipc L4_EXPORT {
24 
25 // ---------------------------------------------------------------
26 /**
27  * Dynamically sized output array of type T.
28  * \tparam T The data-type of each array element.
29  *
30  * Ret_array<> is a special dynamically sized output array
31  * where the number of transmitted elements is passed in
32  * the return value of the call (if positive)
33  */
34 template<typename T> struct L4_EXPORT Ret_array
35 {
36  typedef T const **ptr_type;
37 
38  T *value;
39  unsigned max;
40  Ret_array() {}
41  Ret_array(T *v, unsigned max) : value(v), max(max) {}
42 };
43 
44 namespace Msg {
45 
46 template<typename A> struct Elem< Ret_array<A> >
47 {
48  enum { Is_optional = false };
49  typedef Ret_array<A> type;
50  typedef typename type::ptr_type arg_type;
51  typedef type svr_type;
52  typedef type svr_arg_type;
53 };
54 
55 template<typename A>
56 struct Is_valid_rpc_type<Ret_array<A> *> : L4::Types::False {};
57 template<typename A>
58 struct Is_valid_rpc_type<Ret_array<A> &> : L4::Types::False {};
59 template<typename A>
60 struct Is_valid_rpc_type<Ret_array<A> const &> : L4::Types::False {};
61 template<typename A>
62 struct Is_valid_rpc_type<Ret_array<A> const *> : L4::Types::False {};
63 
64 template<typename A> struct Class< Ret_array<A> > : Class<A>::type {};
65 template<typename A> struct Direction< Ret_array<A> > : Dir_out {};
66 
67 template<typename A, typename CLASS>
68 struct Clnt_val_ops<A const *, Dir_out, CLASS> : Clnt_noops<A const *>
69 {
70  using Clnt_noops<A const *>::from_msg;
71  static int from_msg(char *msg, unsigned offset, unsigned limit, long ret,
72  A const *&arg, Dir_out, Cls_data)
73  {
74  offset = align_to<A>(offset);
75  arg = reinterpret_cast<A const *>(msg + offset);
76  if (L4_UNLIKELY(!check_size<A>(offset, limit, ret)))
77  return -1;
78 
79  return offset + ret * sizeof(A);
80  }
81 };
82 
83 template<typename A, typename CLASS>
84 struct Svr_val_ops<Ret_array<A>, Dir_out, CLASS> :
85  Svr_noops<Ret_array<A> >
86 {
87  typedef Ret_array<A> ret_array;
88  using Svr_noops<ret_array>::from_svr;
89  static int from_svr(char *, unsigned offset, unsigned limit, long ret,
90  ret_array const &, Dir_out, CLASS)
91  {
92  offset = align_to<A>(offset);
93  if (L4_UNLIKELY(!check_size<A>(offset, limit, ret)))
94  return -1;
95  offset += sizeof(A) * ret;
96  return offset;
97  }
98 
99  using Svr_noops<ret_array>::to_svr;
100  static int to_svr(char *msg, unsigned offset, unsigned limit,
101  ret_array &arg, Dir_out, CLASS)
102  {
103  // there can be actually no limit check here, as this
104  // is variably sized output array
105  // FIXME: we could somehow makesure that this is the last
106  // output value...
107  offset = align_to<A>(offset);
108  arg = ret_array(reinterpret_cast<A*>(msg + offset),
109  (limit - offset) / sizeof(A));
110  // FIXME: we dont know the length of the array here so, cheat
111  return offset;
112  }
113 };
114 } // namespace Msg
115 
116 }}