L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
ipc_varg
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 "types"
22#include "ipc_basics"
23
24namespace L4 { namespace Ipc L4_EXPORT {
25
26template< typename T, template <typename X> class B >
27struct Generic_va_type : B<T>
28{
29 enum { Id = B<T>::Id };
30 typedef B<T> ID;
31 typedef T const &Ret_value;
32 typedef T Value;
33
34 static Ret_value value(void const *d)
35 { return *reinterpret_cast<Value const *>(d); }
36
37 static void const *addr_of(Value const &v) { return &v; }
38
39 static unsigned size(void const *) { return sizeof(T); }
40
41 static L4_varg_type unsigned_id()
42 {
43 return static_cast<L4_varg_type>(Id & ~L4_VARG_TYPE_SIGN);
44 }
45
46 static L4_varg_type signed_id()
47 {
48 return static_cast<L4_varg_type>(Id | L4_VARG_TYPE_SIGN);
49 }
50
51 static L4_varg_type id()
52 {
53 return static_cast<L4_varg_type>(Id);
54 }
55};
56
57template< typename T > struct Va_type_id;
58template<> struct Va_type_id<l4_umword_t> { enum { Id = L4_VARG_TYPE_UMWORD }; };
59template<> struct Va_type_id<l4_mword_t> { enum { Id = L4_VARG_TYPE_MWORD }; };
60template<> struct Va_type_id<l4_fpage_t> { enum { Id = L4_VARG_TYPE_FPAGE }; };
61template<> struct Va_type_id<void> { enum { Id = L4_VARG_TYPE_NIL }; };
62template<> struct Va_type_id<char const *> { enum { Id = L4_VARG_TYPE_STRING }; };
63
64template< typename T > struct Va_type;
65
66template<> struct Va_type<l4_umword_t> : Generic_va_type<l4_umword_t, Va_type_id> {};
67template<> struct Va_type<l4_mword_t> : Generic_va_type<l4_mword_t, Va_type_id> {};
68template<> struct Va_type<l4_fpage_t> : Generic_va_type<l4_fpage_t, Va_type_id> {};
69
70template<> struct Va_type<void>
71{
72 typedef void Ret_value;
73 typedef void Value;
74
75 static void const *addr_of(void) { return 0; }
76
77 static void value(void const *) {}
78 static L4_varg_type id() { return L4_VARG_TYPE_NIL; }
79 static unsigned size(void const *) { return 0; }
80};
81
82template<> struct Va_type<char const *>
83{
84 typedef char const *Ret_value;
85 typedef char const *Value;
86
87 static void const *addr_of(Value v) { return v; }
88
89 static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
90 static unsigned size(void const *s)
91 {
92 char const *_s = reinterpret_cast<char const *>(s);
93 int l = 1;
94 while (*_s)
95 {
96 ++_s; ++l;
97 }
98 return l;
99 }
100
101 static Ret_value value(void const *d) { return static_cast<char const *>(d); }
102};
103
107class Varg
108{
109private:
110 enum { Direct_data = 0x8000 };
111 l4_umword_t _tag;
112 char const *_d;
113
114public:
115
118
120 L4_varg_type type() const { return static_cast<L4_varg_type>(_tag & 0xff); }
125 unsigned length() const { return _tag >> 16; }
127 Tag tag() const { return _tag & ~Direct_data; }
129 void tag(Tag tag) { _tag = tag; }
131 void data(char const *d) { _d = d; }
132
134 char const *data() const
135 {
136 if (_tag & Direct_data)
137 {
138 union T { char const *d; char v[sizeof(char const *)]; };
139 return reinterpret_cast<T const *>(&_d)->v;
140 }
141 return _d;
142 }
143
145#if __cplusplus >= 201103L
146 Varg() = default;
147#else
148 Varg() {}
149#endif
150
152 Varg(L4_varg_type t, void const *v, int len)
153 : _tag(t | (static_cast<l4_mword_t>(len) << 16)),
154 _d(static_cast<char const *>(v))
155 {}
156
157 static Varg nil() { return Varg(L4_VARG_TYPE_NIL, 0, 0); }
158
165 template< typename V >
166 typename Va_type<V>::Ret_value value() const
167 {
168 if (_tag & Direct_data)
169 {
170 union X { char const *d; V v; };
171 return reinterpret_cast<X const &>(_d).v;
172 }
173
174 return Va_type<V>::value(_d);
175 }
176
177
179 template< typename T >
180 bool is_of() const { return Va_type<T>::id() == type(); }
181
183 bool is_nil() const { return is_of<void>(); }
184
186 bool is_of_int() const
187 { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
188
195 template< typename T >
196 bool get_value(typename Va_type<T>::Value *v) const
197 {
198 if (!is_of<T>())
199 return false;
200
201 *v = this->value<T>();
202 return true;
203 }
204
206 template< typename T >
207 void set_value(void const *d)
208 {
209 typedef Va_type<T> Vt;
210 _tag = Vt::id() | (Vt::size(d) << 16);
211 _d = static_cast<char const *>(d);
212 }
213
215 template<typename T>
216 void set_direct_value(T val, typename L4::Types::Enable_if<sizeof(T) <= sizeof(char const *), bool>::type = true)
217 {
218 static_assert(sizeof(T) <= sizeof(char const *), "direct Varg value too big");
219 typedef Va_type<T> Vt;
220 _tag = Vt::id() | (sizeof(T) << 16) | Direct_data;
221 union X { char const *d; T v; };
222 reinterpret_cast<X &>(_d).v = val;
223 }
224
226 template<typename T> explicit
227 Varg(T const *data) { set_value<T>(data); }
229 Varg(char const *data) { set_value<char const *>(data); }
230
232 template<typename T> explicit
233 Varg(T data, typename L4::Types::Enable_if<sizeof(T) <= sizeof(char const *), bool>::type = true)
234 { set_direct_value<T>(data); }
235};
236
237
238template<typename T>
239class Varg_t : public Varg
240{
241public:
242 typedef typename Va_type<T>::Value Value;
243 explicit Varg_t(Value v) : Varg()
244 { _data = v; set_value<T>(Va_type<T>::addr_of(_data)); }
245
246private:
247 Value _data;
248};
249
250template<unsigned MAX = L4_UTCB_GENERIC_DATA_SIZE>
251class Varg_list;
252
265{
266private:
267 template<unsigned T>
268 friend class Varg_list;
269
271 class Iter_state
272 {
273 private:
274 using M = l4_umword_t;
275 using Mp = M const *;
276 Mp _c;
277 Mp _e;
278
280 Mp next_arg(Varg const &a) const
281 {
282 return _c + 1 + (Msg::align_to<M>(a.length()) / sizeof(M));
283 }
284
285 public:
287 Iter_state() : _c(nullptr), _e(nullptr) {}
288
290 Iter_state(Mp c, Mp e) : _c(c), _e(e)
291 {}
292
294 bool valid() const
295 { return _c && _c < _e; }
296
298 Mp begin() const { return _c; }
299
301 Mp end() const { return _e; }
302
307 Varg pop()
308 {
309 if (!valid())
310 return Varg::nil();
311
312 Varg a;
313 a.tag(_c[0]);
314 a.data(reinterpret_cast<char const *>(&_c[1]));
315 _c = next_arg(a);
316 if (_c > _e)
317 return Varg::nil();
318
319 return a;
320 }
321
323 bool operator == (Iter_state const &o) const
324 { return _c == o._c; }
325
327 bool operator != (Iter_state const &o) const
328 { return _c != o._c; }
329 };
330
331 Iter_state _s;
332
333public:
335 Varg_list_ref() = default;
336
343 Varg_list_ref(void const *start, void const *end)
344 : _s(reinterpret_cast<l4_umword_t const *>(start),
345 reinterpret_cast<l4_umword_t const *>(end))
346 {}
347
350 {
351 private:
352 Iter_state _s;
353 Varg _a;
354
355 public:
357 Iterator(Iter_state const &s)
358 : _s(s)
359 {
360 _a = _s.pop();
361 }
362
364 explicit operator bool () const
365 { return !_a.is_nil(); }
366
369 {
370 if (!_a.is_nil())
371 _a = _s.pop();
372
373 return *this;
374 }
375
378 { return _a; }
379
381 bool equals(Iterator const &o) const
382 {
383 if (_a.is_nil() && o._a.is_nil())
384 return true;
385
386 return _s == o._s;
387 }
388
389 bool operator == (Iterator const &o) const
390 { return equals(o); }
391
392 bool operator != (Iterator const &o) const
393 { return !equals(o); }
394 };
395
398 { return _s.pop(); }
399
402 L4_DEPRECATED("Use range for or pop_front.")
403 { return _s.pop(); }
404
407 { return Iterator(_s); }
408
410 Iterator end() const
411 { return Iterator(Iter_state()); }
412};
413
421template<unsigned MAX>
423{
424 l4_umword_t data[MAX];
425 Varg_list(Varg_list const &);
426
427public:
430 {
431 if (!r._s.valid())
432 return;
433
434 l4_umword_t const *rs = r._s.begin();
435 unsigned c = r._s.end() - rs;
436 for (unsigned i = 0; i < c; ++i)
437 data[i] = rs[i];
438
439 this->_s = Iter_state(data, data + c);
440 }
441};
442
443
444namespace Msg {
445template<> struct Elem<Varg const *>
446{
447 typedef Varg const *arg_type;
448 typedef Varg_list_ref svr_type;
449 typedef Varg_list_ref svr_arg_type;
450 enum { Is_optional = false };
451};
452
453template<> struct Is_valid_rpc_type<Varg> : L4::Types::False {};
454template<> struct Is_valid_rpc_type<Varg *> : L4::Types::False {};
455template<> struct Is_valid_rpc_type<Varg &> : L4::Types::False {};
456template<> struct Is_valid_rpc_type<Varg const &> : L4::Types::False {};
457
458template<> struct Direction<Varg const *> : Dir_in {};
459template<> struct Class<Varg const *> : Cls_data {};
460
461template<typename DIR, typename CLASS>
462struct Clnt_val_ops<Varg, DIR, CLASS>;
463
464template<>
465struct Clnt_val_ops<Varg, Dir_in, Cls_data> :
466 Clnt_noops<Varg const &>
467{
468 using Clnt_noops<Varg const &>::to_msg;
469 static int to_msg(char *msg, unsigned offs, unsigned limit,
470 Varg const &a, Dir_in, Cls_data)
471 {
472 for (Varg const *i = &a; i->tag(); ++i)
473 {
474 offs = align_to<l4_umword_t>(offs);
475 if (L4_UNLIKELY(!check_size<l4_umword_t>(offs, limit)))
476 return -L4_EMSGTOOLONG;
477 *reinterpret_cast<l4_umword_t*>(msg + offs) = i->tag();
478 offs += sizeof(l4_umword_t);
479 if (L4_UNLIKELY(!check_size<char>(offs, limit, i->length())))
480 return -L4_EMSGTOOLONG;
481 char const *d = i->data();
482 for (unsigned x = 0; x < i->length(); ++x)
483 msg[offs++] = *d++;
484 }
485
486 return offs;
487 }
488};
489
490template<>
491struct Svr_val_ops<Varg_list_ref, Dir_in, Cls_data> :
492 Svr_noops<Varg_list_ref>
493{
494 using Svr_noops<Varg_list_ref>::to_svr;
495 static int to_svr(char *msg, unsigned offset, unsigned limit,
496 Varg_list_ref &a, Dir_in, Cls_data)
497 {
498 unsigned start = align_to<l4_umword_t>(offset);
499 unsigned offs;
500 for (offs = start; offs < limit;)
501 {
502 unsigned noffs = align_to<l4_umword_t>(offs);
503 if (L4_UNLIKELY(!check_size<l4_umword_t>(noffs, limit)))
504 break;
505
506 offs = noffs;
507 Varg arg;
508 arg.tag(*reinterpret_cast<l4_umword_t*>(msg + offs));
509
510 if (!arg.tag())
511 break;
512
513 offs += sizeof(l4_umword_t);
514
515 if (L4_UNLIKELY(!check_size<char>(offs, limit, arg.length())))
516 return -L4_EMSGTOOLONG;
517 offs += arg.length();
518 }
519
520 a = Varg_list_ref(msg + start, msg + align_to<l4_umword_t>(offs));
521 return offs;
522 }
523};
524}
525}}
Iterator for Valists.
Definition ipc_varg:350
Iterator(Iter_state const &s)
Create a new iterator.
Definition ipc_varg:357
bool equals(Iterator const &o) const
check for equality
Definition ipc_varg:381
Iterator & operator++()
increment iterator to the next arg
Definition ipc_varg:368
Varg operator*() const
dereference the iterator, get Varg
Definition ipc_varg:377
List of variable-sized RPC parameters as received by the server.
Definition ipc_varg:265
Iterator begin() const
Returns an interator to the first Varg.
Definition ipc_varg:406
Varg pop_front()
Get the next parameter in the list.
Definition ipc_varg:397
Varg next()
Get the next parameter in the list.
Definition ipc_varg:401
Varg_list_ref(void const *start, void const *end)
Create a parameter list over a given memory region.
Definition ipc_varg:343
Iterator end() const
Returns the end of the list.
Definition ipc_varg:410
Varg_list_ref()=default
Create an empty parameter list.
Self-contained list of variable-sized RPC parameters.
Definition ipc_varg:423
Varg_list(Varg_list_ref const &r)
Create a parameter list as a copy from a referencing list.
Definition ipc_varg:429
Variably sized RPC argument.
Definition ipc_varg:108
bool is_of_int() const
Definition ipc_varg:186
Varg(char const *data)
Make Varg from null-terminated string.
Definition ipc_varg:229
char const * data() const
Definition ipc_varg:134
Varg(L4_varg_type t, void const *v, int len)
Make an indirect varg.
Definition ipc_varg:152
Varg()=default
Make uninitialized Varg.
l4_umword_t Tag
The data type for the tag.
Definition ipc_varg:117
Va_type< V >::Ret_value value() const
Definition ipc_varg:166
bool is_of() const
Definition ipc_varg:180
void set_direct_value(T val, typename L4::Types::Enable_if< sizeof(T)<=sizeof(char const *), bool >::type=true)
Set to directly stored value of type T.
Definition ipc_varg:216
unsigned length() const
Get the size of the RPC argument.
Definition ipc_varg:125
void set_value(void const *d)
Set to indirect value of type T.
Definition ipc_varg:207
Tag tag() const
Definition ipc_varg:127
L4_varg_type type() const
Definition ipc_varg:120
void tag(Tag tag)
Set Varg tag (usually from message)
Definition ipc_varg:129
Varg(T const *data)
Make Varg from indirect value (pointer)
Definition ipc_varg:227
Varg(T data, typename L4::Types::Enable_if< sizeof(T)<=sizeof(char const *), bool >::type=true)
Make Varg from direct value.
Definition ipc_varg:233
void data(char const *d)
Set Varg to indirect data value (usually in UTCB)
Definition ipc_varg:131
bool is_nil() const
Definition ipc_varg:183
bool get_value(typename Va_type< T >::Value *v) const
Get the value of the Varg as type T.
Definition ipc_varg:196
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:51
signed long l4_mword_t
Signed machine word.
Definition l4int.h:48
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:68
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:296
#define L4_EXPORT
Attribute to mark functions, variables, and data types as being exported from a library.
Definition compiler.h:231
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition compiler.h:301
L4 low-level kernel interface.
Definition io_regblock.h:19
False meta value.
Definition types:307
L4 flexpage type.
Definition __l4_fpage.h:85