L4Re - L4 Runtime Environment
ipc_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 #include "ipc_types"
23 
24 namespace L4 { namespace Ipc L4_EXPORT {
25 
27 typedef unsigned short Array_len_default;
28 
38 template< typename ELEM_TYPE, typename LEN_TYPE = Array_len_default >
39 struct Array_ref
40 {
41  typedef ELEM_TYPE *ptr_type;
42  typedef LEN_TYPE len_type;
43 
44  len_type length;
45  ptr_type data;
46  Array_ref() {}
47  Array_ref(len_type length, ptr_type data)
48  : length(length), data(data)
49  {}
50 
51  template<typename X> struct Non_const
52  { typedef Array_ref<X, LEN_TYPE> type; };
53 
54  template<typename X> struct Non_const<X const>
55  { typedef Array_ref<X, LEN_TYPE> type; };
56 
57  Array_ref(typename Non_const<ELEM_TYPE>::type const &other)
58  : length(other.length), data(other.data)
59  {}
60 };
61 
84 template<typename ELEM_TYPE, typename LEN_TYPE = Array_len_default>
85 struct Array : Array_ref<ELEM_TYPE , LEN_TYPE>
86 {
88  Array() {}
90  Array(LEN_TYPE length, ELEM_TYPE *data)
91  : Array_ref<ELEM_TYPE, LEN_TYPE>(length, data)
92  {}
93 
94  template<typename X> struct Non_const
95  { typedef Array<X, LEN_TYPE> type; };
96 
97  template<typename X> struct Non_const<X const>
98  { typedef Array<X, LEN_TYPE> type; };
99 
101  Array(typename Non_const<ELEM_TYPE>::type const &other)
102  : Array_ref<ELEM_TYPE, LEN_TYPE>(other.length, other.data)
103  {}
104 };
105 
119 template< typename ELEM_TYPE,
120  typename LEN_TYPE = Array_len_default,
121  LEN_TYPE MAX = (L4_UTCB_GENERIC_DATA_SIZE *
122  sizeof(l4_umword_t)) / sizeof(ELEM_TYPE) >
124 {
127 
129  ELEM_TYPE data[MAX];
131  LEN_TYPE length;
132 
134  void copy_in(const_array a)
135  {
136  length = a.length;
137  if (length > MAX)
138  length = MAX;
139 
140  for (LEN_TYPE i = 0; i < length; ++i)
141  data[i] = a.data[i];
142  }
143 
145  Array_in_buf(const_array a) { copy_in(a); }
147  Array_in_buf(array a) { copy_in(a); }
148 };
149 
150 // implementation details for transmission
151 namespace Msg {
152 
154 template<typename A, typename LEN>
155 struct Elem< Array<A, LEN> >
156 {
161  typedef svr_type svr_arg_type;
162  enum { Is_optional = false };
163 };
164 
166 template<typename A, typename LEN>
167 struct Elem< Array<A, LEN> & >
168 {
174  typedef svr_type &svr_arg_type;
175  enum { Is_optional = false };
176 };
177 
179 template<typename A, typename LEN>
180 struct Elem< Array_ref<A, LEN> & >
181 {
187  typedef svr_type &svr_arg_type;
188  enum { Is_optional = false };
189 };
190 
191 template<typename A> struct Class<Array<A> > : Class<A>::type {};
192 template<typename A> struct Class<Array_ref<A> > : Class<A>::type {};
193 
194 namespace Detail {
195 
196 template<typename A, typename LEN, typename ARRAY, bool REF>
197 struct Clnt_val_ops_d_in : Clnt_noops<ARRAY>
198 {
199  using Clnt_noops<ARRAY>::to_msg;
200  static int to_msg(char *msg, unsigned offset, unsigned limit,
201  ARRAY a, Dir_in, Cls_data)
202  {
203  offset = align_to<LEN>(offset);
204  if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
205  return -L4_EMSGTOOLONG;
206  *reinterpret_cast<LEN *>(msg + offset) = a.length;
207  offset = align_to<A>(offset + sizeof(LEN));
208  if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
209  return -L4_EMSGTOOLONG;
210  typedef typename L4::Types::Remove_const<A>::type elem_type;
211  elem_type *data = reinterpret_cast<elem_type*>(msg + offset);
212 
213  // we do not correctly handle overlaps
214  if (!REF || data != a.data)
215  for (LEN i = 0; i < a.length; ++i)
216  data[i] = a.data[i];
217 
218  return offset + a.length * sizeof(A);
219  }
220 };
221 } // namespace Detail
222 
223 template<typename A, typename LEN>
224 struct Clnt_val_ops<Array<A, LEN>, Dir_in, Cls_data> :
225  Detail::Clnt_val_ops_d_in<A, LEN, Array<A, LEN>, false> {};
226 
227 template<typename A, typename LEN>
228 struct Clnt_val_ops<Array_ref<A, LEN>, Dir_in, Cls_data> :
229  Detail::Clnt_val_ops_d_in<A, LEN, Array_ref<A, LEN>, true> {};
230 
231 template<typename A, typename LEN, typename CLASS>
232 struct Svr_val_ops< Array_ref<A, LEN>, Dir_in, CLASS >
233 : Svr_noops< Array_ref<A, LEN> >
234 {
235  typedef Array_ref<A, LEN> svr_type;
236 
237  using Svr_noops<svr_type>::to_svr;
238  static int to_svr(char *msg, unsigned offset, unsigned limit,
239  svr_type &a, Dir_in, Cls_data)
240  {
241  offset = align_to<LEN>(offset);
242  if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
243  return -L4_EMSGTOOSHORT;
244  a.length = *reinterpret_cast<LEN *>(msg + offset);
245  offset = align_to<A>(offset + sizeof(LEN));
246  if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
247  return -L4_EMSGTOOSHORT;
248  a.data = reinterpret_cast<A*>(msg + offset);
249  return offset + a.length * sizeof(A);
250  }
251 };
252 
253 template<typename A, typename LEN>
254 struct Svr_xmit< Array<A, LEN> > : Svr_xmit< Array_ref<A, LEN> > {};
255 
256 template<typename A, typename LEN>
257 struct Clnt_val_ops<Array<A, LEN>, Dir_out, Cls_data> : Clnt_noops<Array<A, LEN> >
258 {
259  typedef Array<A, LEN> type;
260 
261  using Clnt_noops<type>::from_msg;
262  static int from_msg(char *msg, unsigned offset, unsigned limit, long,
263  type &a, Dir_out, Cls_data)
264  {
265  offset = align_to<LEN>(offset);
266  if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
267  return -L4_EMSGTOOSHORT;
268 
269  LEN l = *reinterpret_cast<LEN *>(msg + offset);
270 
271  offset = align_to<A>(offset + sizeof(LEN));
272  if (L4_UNLIKELY(!check_size<A>(offset, limit, l)))
273  return -L4_EMSGTOOSHORT;
274 
275  A *data = reinterpret_cast<A*>(msg + offset);
276 
277  if (l > a.length)
278  l = a.length;
279  else
280  a.length = l;
281 
282  for (unsigned i = 0; i < l; ++i)
283  a.data[i] = data[i];
284 
285  return offset + l * sizeof(A);
286  };
287 };
288 
289 template<typename A, typename LEN>
290 struct Clnt_val_ops<Array_ref<A, LEN>, Dir_out, Cls_data> :
291  Clnt_noops<Array_ref<A, LEN> >
292 {
293  typedef Array_ref<A, LEN> type;
294 
295  using Clnt_noops<type>::from_msg;
296  static int from_msg(char *msg, unsigned offset, unsigned limit, long,
297  type &a, Dir_out, Cls_data)
298  {
299  offset = align_to<LEN>(offset);
300  if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
301  return -L4_EMSGTOOSHORT;
302 
303  LEN l = *reinterpret_cast<LEN *>(msg + offset);
304 
305  offset = align_to<A>(offset + sizeof(LEN));
306  if (L4_UNLIKELY(!check_size<A>(offset, limit, l)))
307  return -L4_EMSGTOOSHORT;
308 
309  a.data = reinterpret_cast<A*>(msg + offset);
310  a.length = l;
311  return offset + l * sizeof(A);
312  };
313 };
314 
315 template<typename A, typename LEN, typename CLASS>
316 struct Svr_val_ops<Array_ref<A, LEN>, Dir_out, CLASS> :
317  Svr_noops<Array_ref<typename L4::Types::Remove_const<A>::type, LEN> &>
318 {
319  typedef typename L4::Types::Remove_const<A>::type elem_type;
321 
322  using Svr_noops<svr_type>::to_svr;
323  static int to_svr(char *msg, unsigned offset, unsigned limit,
324  svr_type a, Dir_out, Cls_data)
325  {
326  offset = align_to<LEN>(offset);
327  if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
328  return -L4_EMSGTOOLONG;
329 
330  offset = align_to<A>(offset + sizeof(LEN));
331  a.data = reinterpret_cast<elem_type *>(msg + offset);
332  a.length = (limit-offset) / sizeof(A);
333  return offset;
334  }
335 
336  using Svr_noops<svr_type>::from_svr;
337  static int from_svr(char *msg, unsigned offset, unsigned limit, long,
338  svr_type a, Dir_out, Cls_data)
339  {
340  offset = align_to<LEN>(offset);
341  if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
342  return -L4_EMSGTOOLONG;
343 
344  *reinterpret_cast<LEN *>(msg + offset) = a.length;
345 
346  offset = align_to<A>(offset + sizeof(LEN));
347  if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
348  return -L4_EMSGTOOLONG;
349 
350  return offset + a.length * sizeof(A);
351  }
352 };
353 
354 template<typename A, typename LEN>
355 struct Svr_xmit<Array<A, LEN> &> : Svr_xmit<Array_ref<A, LEN> &> {};
356 
357 // Pointer to array is not implemented.
358 template<typename A, typename LEN>
359 struct Is_valid_rpc_type< Array_ref<A, LEN> *> : L4::Types::False {};
360 
361 // Optional input arrays are not implemented.
362 template<typename A, typename LEN>
363 struct Is_valid_rpc_type< Opt<Array_ref<A, LEN> > > : L4::Types::False {};
364 
365 } // namespace Msg
366 
367 }}
svr_type & svr_arg_type
Array_ref<> & at the server side.
Definition: ipc_array:174
Message too long.
Definition: err.h:67
Total number of message register (MRs) available.
Definition: utcb.h:47
Array(typename Non_const< ELEM_TYPE >::type const &other)
Make a const array from a non-const array.
Definition: ipc_array:101
unsigned short Array_len_default
Default type for passing length of an array.
Definition: ipc_array:27
Array_in_buf(const_array a)
Make Array_in_buf from a const array.
Definition: ipc_array:145
L4 low-level kernel interface.
Array< A, LEN > & arg_type
Array<> & at the interface.
Definition: ipc_array:170
Array_ref< A, LEN > svr_type
Array_ref<> as server storage type.
Definition: ipc_array:172
void copy_in(const_array a)
copy in data from a source array
Definition: ipc_array:134
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition: compiler.h:234
LEN_TYPE length
The length of the array.
Definition: ipc_array:131
Array_in_buf(array a)
Make Array_in_buf from a non-const array.
Definition: ipc_array:147
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:52
Server-side copy in buffer for Array.
Definition: ipc_array:123
Array_ref< typename L4::Types::Remove_const< A >::type, LEN > svr_type
Array_ref<> as server storage.
Definition: ipc_array:185
Array(LEN_TYPE length, ELEM_TYPE *data)
Make array from length and data pointer.
Definition: ipc_array:90
Type trait defining a valid RPC parameter type.
Definition: ipc_basics:350
Marker type for input values.
Definition: ipc_basics:156
Array_ref< A, LEN > & arg_type
Array_ref<> at the interface.
Definition: ipc_array:183
Defines client-side handling of `MTYPE&#39; as RPC argument.
Definition: ipc_basics:221
Array reference data type for arrays located in the message.
Definition: ipc_array:39
Defines server-side handling for MTYPE server arguments.
Definition: ipc_basics:275
Marker type for data values.
Definition: ipc_basics:161
Array()
Make array.
Definition: ipc_array:88
Array data type for dynamically sized arrays in RPCs.
Definition: ipc_array:85
Message too short.
Definition: err.h:66
Array_ref< A, LEN > svr_type
Array_ref<> at the server side.
Definition: ipc_array:160
False meta value.
Definition: types:173
svr_type & svr_arg_type
Array_ref<> & as server argument.
Definition: ipc_array:187
Array< A, LEN > arg_type
Array<> as argument at the interface.
Definition: ipc_array:158