L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
ipc_array
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7#pragma once
8
9#include "types"
10#include "ipc_basics"
11#include "ipc_types"
12
13namespace L4 { namespace Ipc L4_EXPORT {
14
16using Array_len_default = unsigned short;
17
27template< typename ELEM_TYPE, typename LEN_TYPE = Array_len_default >
28struct Array_ref
29{
30 using ptr_type = ELEM_TYPE *;
31 using len_type = LEN_TYPE;
32
33 len_type length;
34 ptr_type data;
35 Array_ref() = default;
36 Array_ref(len_type length, ptr_type data)
37 : length(length), data(data)
38 {}
39
40 template<typename X> struct Non_const
41 { using type = Array_ref<X, LEN_TYPE>; };
42
43 template<typename X> struct Non_const<X const>
44 { using type = Array_ref<X, LEN_TYPE>; };
45
46 Array_ref(typename Non_const<ELEM_TYPE>::type const &other)
47 : length(other.length), data(other.data)
48 {}
49
50 Array_ref &operator = (typename Non_const<ELEM_TYPE>::type const &other)
51 {
52 this->length = other.length;
53 this->data = other.data;
54 return *this;
55 }
56};
57
80template<typename ELEM_TYPE, typename LEN_TYPE = Array_len_default>
81struct Array : Array_ref<ELEM_TYPE , LEN_TYPE>
82{
84 Array() {}
86 Array(LEN_TYPE length, ELEM_TYPE *data)
87 : Array_ref<ELEM_TYPE, LEN_TYPE>(length, data)
88 {}
89
90 template<typename X> struct Non_const
91 { using type = Array<X, LEN_TYPE>; };
92
93 template<typename X> struct Non_const<X const>
94 { using type = Array<X, LEN_TYPE>; };
95
97 Array(typename Non_const<ELEM_TYPE>::type const &other)
98 : Array_ref<ELEM_TYPE, LEN_TYPE>(other.length, other.data)
99 {}
100
101 Array &operator = (typename Non_const<ELEM_TYPE>::type const &other)
102 {
103 this->length = other.length;
104 this->data = other.data;
105 return *this;
106 }
107};
108
122template< typename ELEM_TYPE,
123 typename LEN_TYPE = Array_len_default,
124 LEN_TYPE MAX = (L4_UTCB_GENERIC_DATA_SIZE *
125 sizeof(l4_umword_t)) / sizeof(ELEM_TYPE) >
127{
128 using array = Array_ref<ELEM_TYPE, LEN_TYPE>;
129 using const_array = Array_ref<ELEM_TYPE const, LEN_TYPE>;
130
132 ELEM_TYPE data[MAX];
134 LEN_TYPE length;
135
137 void copy_in(const_array a)
138 {
139 length = a.length;
140 if (length > MAX)
141 length = MAX;
142
143 for (LEN_TYPE i = 0; i < length; ++i)
144 data[i] = a.data[i];
145 }
146
148 Array_in_buf(const_array a) { copy_in(a); }
150 Array_in_buf(array a) { copy_in(a); }
151};
152
153// implementation details for transmission
154namespace Msg {
155
157template<typename A, typename LEN>
158struct Elem< Array<A, LEN> >
159{
164 using svr_arg_type = svr_type;
165 static constexpr bool Is_optional = false;
166 static constexpr bool Is_input = true;
167 static constexpr bool Is_output = false;
168};
169
171template<typename A, typename LEN>
172struct Elem< Array<A, LEN> & >
173{
180 static constexpr bool Is_optional = false;
181 static constexpr bool Is_input = false;
182 static constexpr bool Is_output = true;
183};
184
186template<typename A, typename LEN>
187struct Elem< Array_ref<A, LEN> & >
188{
195 static constexpr bool Is_optional = false;
196 static constexpr bool Is_input = false;
197 static constexpr bool Is_output = true;
198};
199
200namespace Detail {
201
202template<typename A, typename LEN, typename ARRAY, bool REF>
203struct Clnt_val_ops_d_in : Clnt_noops<ARRAY>
204{
205 static int to_msg_data(char *msg, unsigned offset, unsigned limit,
206 ARRAY const &a)
207 {
208 offset = align_to<LEN>(offset);
209 if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
210 return -L4_EMSGTOOLONG;
211 *reinterpret_cast<LEN *>(msg + offset) = a.length;
212 offset = align_to<A>(offset + sizeof(LEN));
213 if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
214 return -L4_EMSGTOOLONG;
215 using elem_type = L4::Types::Remove_const_t<A>;
216 elem_type *data = reinterpret_cast<elem_type*>(msg + offset);
217
218 // we do not correctly handle overlaps
219 if (!REF || data != a.data)
220 {
221 for (LEN i = 0; i < a.length; ++i)
222 data[i] = a.data[i];
223 }
224
225 return offset + a.length * sizeof(A);
226 }
227};
228
229} // namespace Detail
230
231template<typename A, typename LEN>
232struct Clnt_val_ops<Array<A, LEN>> :
233 Detail::Clnt_val_ops_d_in<A, LEN, Array<A, LEN>, false>
234{
235 using type = Array<A, LEN>;
236
237 static int from_msg_data(char *msg, unsigned offset, unsigned limit, type &a)
238 {
239 offset = align_to<LEN>(offset);
240 if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
241 return -L4_EMSGTOOSHORT;
242
243 LEN l = *reinterpret_cast<LEN *>(msg + offset);
244
245 offset = align_to<A>(offset + sizeof(LEN));
246 if (L4_UNLIKELY(!check_size<A>(offset, limit, l)))
247 return -L4_EMSGTOOSHORT;
248
249 A *data = reinterpret_cast<A*>(msg + offset);
250
251 if (l > a.length)
252 l = a.length;
253 else
254 a.length = l;
255
256 for (unsigned i = 0; i < l; ++i)
257 a.data[i] = data[i];
258
259 return offset + l * sizeof(A);
260 };
261};
262
263template<typename A, typename LEN>
264struct Clnt_val_ops<Array_ref<A, LEN>> :
265 Detail::Clnt_val_ops_d_in<A, LEN, Array_ref<A, LEN>, true>
266{
267 using type = Array_ref<A, LEN>;
268
269 static int from_msg_data(char *msg, unsigned offset, unsigned limit, type &a)
270 {
271 offset = align_to<LEN>(offset);
272 if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
273 return -L4_EMSGTOOSHORT;
274
275 LEN l = *reinterpret_cast<LEN *>(msg + offset);
276
277 offset = align_to<A>(offset + sizeof(LEN));
278 if (L4_UNLIKELY(!check_size<A>(offset, limit, l)))
279 return -L4_EMSGTOOSHORT;
280
281 a.data = reinterpret_cast<A*>(msg + offset);
282 a.length = l;
283 return offset + l * sizeof(A);
284 };
285};
286
287template<typename A, typename LEN>
288struct Svr_val_ops< Array_ref<A, LEN> > :
289 Svr_noops< Array_ref<A, LEN> >
290{
291 using svr_type = Array_ref<A, LEN>;
292 using elem_type = L4::Types::Remove_const_t<A>;
293
294 static int to_svr_data(char *msg, unsigned offset, unsigned limit,
295 svr_type &a)
296 {
297 offset = align_to<LEN>(offset);
298 if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
299 return -L4_EMSGTOOSHORT;
300 a.length = *reinterpret_cast<LEN *>(msg + offset);
301 offset = align_to<A>(offset + sizeof(LEN));
302 if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
303 return -L4_EMSGTOOSHORT;
304 a.data = reinterpret_cast<A*>(msg + offset);
305 return offset + a.length * sizeof(A);
306 }
307
308 static int reserve_data(char *msg, unsigned offset, unsigned limit,
309 svr_type &a)
310 {
311 offset = align_to<LEN>(offset);
312 if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
313 return -L4_EMSGTOOLONG;
314
315 offset = align_to<A>(offset + sizeof(LEN));
316 a.data = reinterpret_cast<elem_type *>(msg + offset);
317 a.length = (limit-offset) / sizeof(A);
318 return offset;
319 }
320
321 static int from_svr_data(char *msg, unsigned offset, unsigned limit,
322 svr_type const &a)
323 {
324 offset = align_to<LEN>(offset);
325 if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
326 return -L4_EMSGTOOLONG;
327
328 *reinterpret_cast<LEN *>(msg + offset) = a.length;
329
330 offset = align_to<A>(offset + sizeof(LEN));
331 if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
332 return -L4_EMSGTOOLONG;
333
334 // In case of deferred replies, the Array_ref is pointing to a server
335 // provided buffer instead of the UTCB.
336 elem_type *data = reinterpret_cast<elem_type *>(msg + offset);
337 if (data != a.data)
338 for (LEN i = 0; i < a.length; ++i)
339 data[i] = a.data[i];
340
341 return offset + a.length * sizeof(A);
342 }
343};
344
345// Pointer to array is not implemented.
346template<typename A, typename LEN>
347struct Is_valid_rpc_type< Array_ref<A, LEN> *> : L4::Types::False {};
348
349// Optional input arrays are not implemented.
350template<typename A, typename LEN>
351struct Is_valid_rpc_type< Opt<Array_ref<A, LEN> > > : L4::Types::False {};
352
353} // namespace Msg
354
355}}
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:59
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:58
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:295
#define L4_EXPORT
Attribute to mark functions, variables, and data types as being exported from a library.
Definition compiler.h:220
IPC Message related functionality.
Definition ipc_array:154
constexpr bool check_size(unsigned offset, unsigned limit) noexcept
Check if there is enough space for T from offset to limit.
Definition ipc_basics:50
constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
Pad bytes to the given alignment align (in bytes).
Definition ipc_basics:27
IPC related functionality.
Definition ipc_array:13
unsigned short Array_len_default
Default type for passing length of an array.
Definition ipc_array:16
L4 low-level kernel interface.
void copy_in(const_array a)
copy in data from a source array
Definition ipc_array:137
Array_in_buf(array a)
Make Array_in_buf from a non-const array.
Definition ipc_array:150
Array_in_buf(const_array a)
Make Array_in_buf from a const array.
Definition ipc_array:148
Array reference data type for arrays located in the message.
Definition ipc_array:29
Array data type for dynamically sized arrays in RPCs.
Definition ipc_array:82
Array()
Make array.
Definition ipc_array:84
Array(LEN_TYPE length, ELEM_TYPE *data)
Make array from length and data pointer.
Definition ipc_array:86
Array(typename Non_const< ELEM_TYPE >::type const &other)
Make a const array from a non-const array.
Definition ipc_array:97
Empty client side marshalling code.
Definition ipc_basics:194
Defines client-side handling of 'MTYPE' as RPC argument.
Definition ipc_basics:409
static int from_msg_data(char *msg, unsigned offset, unsigned limit, MTYPE &arg) noexcept
Copy data from the message to a T client reference (arg must be MTYPE &).
Definition ipc_basics:419
Array_ref< A, LEN > svr_type
Array_ref<> at the server side.
Definition ipc_array:163
Array< A, LEN > arg_type
Array<> as argument at the interface.
Definition ipc_array:161
Array< A, LEN > & arg_type
Array<> & at the interface.
Definition ipc_array:175
Array_ref< A, LEN > svr_type
Array_ref<> as server storage type.
Definition ipc_array:177
svr_type & svr_arg_type
Array_ref<> & at the server side.
Definition ipc_array:179
svr_type & svr_arg_type
Array_ref<> & as server argument.
Definition ipc_array:194
Array_ref< L4::Types::Remove_const_t< A >, LEN > svr_type
Array_ref<> as server storage.
Definition ipc_array:192
Array_ref< A, LEN > & arg_type
Array_ref<> at the interface.
Definition ipc_array:190
Helper struct to describe various aspects of an IPC argument.
Definition ipc_basics:472
Type trait defining a valid RPC parameter type.
Definition ipc_basics:521
Empty server side marshalling code.
Definition ipc_basics:295
Defines server-side handling of 'MTYPE' as RPC argument.
Definition ipc_basics:439
static int to_svr_data(char *msg, unsigned offset, unsigned limit, MTYPE &arg) noexcept
Copy data from the message to a T server reference (arg must be MTYPE &).
Definition ipc_basics:444
static int from_svr_data(char *msg, unsigned offset, unsigned limit, MTYPE const &arg) noexcept
Copy a T into the message (arg must be either MTYPE or MTYPE const &).
Definition ipc_basics:459
static int reserve_data(char *, unsigned offs, unsigned limit, MTYPE &) noexcept
Prepare a T output operand (arg must be MTYPE &).
Definition ipc_basics:449