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() { return (L4_varg_type)(Id & ~L4_VARG_TYPE_SIGN); }
42 static L4_varg_type signed_id() { return (L4_varg_type)(Id | L4_VARG_TYPE_SIGN); }
43 static L4_varg_type id() { return (L4_varg_type)Id; }
44};
45
46template< typename T > struct Va_type_id;
47template<> struct Va_type_id<l4_umword_t> { enum { Id = L4_VARG_TYPE_UMWORD }; };
48template<> struct Va_type_id<l4_mword_t> { enum { Id = L4_VARG_TYPE_MWORD }; };
49template<> struct Va_type_id<l4_fpage_t> { enum { Id = L4_VARG_TYPE_FPAGE }; };
50template<> struct Va_type_id<void> { enum { Id = L4_VARG_TYPE_NIL }; };
51template<> struct Va_type_id<char const *> { enum { Id = L4_VARG_TYPE_STRING }; };
52
53template< typename T > struct Va_type;
54
55template<> struct Va_type<l4_umword_t> : Generic_va_type<l4_umword_t, Va_type_id> {};
56template<> struct Va_type<l4_mword_t> : Generic_va_type<l4_mword_t, Va_type_id> {};
57template<> struct Va_type<l4_fpage_t> : Generic_va_type<l4_fpage_t, Va_type_id> {};
58
59template<> struct Va_type<void>
60{
61 typedef void Ret_value;
62 typedef void Value;
63
64 static void const *addr_of(void) { return 0; }
65
66 static void value(void const *) {}
67 static L4_varg_type id() { return L4_VARG_TYPE_NIL; }
68 static unsigned size(void const *) { return 0; }
69};
70
71template<> struct Va_type<char const *>
72{
73 typedef char const *Ret_value;
74 typedef char const *Value;
75
76 static void const *addr_of(Value v) { return v; }
77
78 static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
79 static unsigned size(void const *s)
80 {
81 char const *_s = reinterpret_cast<char const *>(s);
82 int l = 1;
83 while (*_s)
84 {
85 ++_s; ++l;
86 }
87 return l;
88 }
89
90 static Ret_value value(void const *d) { return (char const *)d; }
91};
92
96class Varg
97{
98private:
99 enum { Direct_data = 0x8000 };
100 l4_umword_t _tag;
101 char const *_d;
102
103public:
104
107
109 L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); }
114 unsigned length() const { return _tag >> 16; }
116 Tag tag() const { return _tag & ~Direct_data; }
118 void tag(Tag tag) { _tag = tag; }
120 void data(char const *d) { _d = d; }
121
123 char const *data() const
124 {
125 if (_tag & Direct_data)
126 {
127 union T { char const *d; char v[sizeof(char const *)]; };
128 return reinterpret_cast<T const *>(&_d)->v;
129 }
130 return _d;
131 }
132
134#if __cplusplus >= 201103L
135 Varg() = default;
136#else
137 Varg() {}
138#endif
139
141 Varg(L4_varg_type t, void const *v, int len)
142 : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v)
143 {}
144
145 static Varg nil() { return Varg(L4_VARG_TYPE_NIL, 0, 0); }
146
153 template< typename V >
154 typename Va_type<V>::Ret_value value() const
155 {
156 if (_tag & Direct_data)
157 {
158 union X { char const *d; V v; };
159 return reinterpret_cast<X const &>(_d).v;
160 }
161
162 return Va_type<V>::value(_d);
163 }
164
165
167 template< typename T >
168 bool is_of() const { return Va_type<T>::id() == type(); }
169
171 bool is_nil() const { return is_of<void>(); }
172
174 bool is_of_int() const
175 { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
176
183 template< typename T >
184 bool get_value(typename Va_type<T>::Value *v) const
185 {
186 if (!is_of<T>())
187 return false;
188
189 *v = this->value<T>();
190 return true;
191 }
192
194 template< typename T >
195 void set_value(void const *d)
196 {
197 typedef Va_type<T> Vt;
198 _tag = Vt::id() | (Vt::size(d) << 16);
199 _d = (char const *)d;
200 }
201
203 template<typename T>
204 void set_direct_value(T val, typename L4::Types::Enable_if<sizeof(T) <= sizeof(char const *), bool>::type = true)
205 {
206 static_assert(sizeof(T) <= sizeof(char const *), "direct Varg value too big");
207 typedef Va_type<T> Vt;
208 _tag = Vt::id() | (sizeof(T) << 16) | Direct_data;
209 union X { char const *d; T v; };
210 reinterpret_cast<X &>(_d).v = val;
211 }
212
214 template<typename T> explicit
215 Varg(T const *data) { set_value<T>(data); }
217 Varg(char const *data) { set_value<char const *>(data); }
218
220 template<typename T> explicit
221 Varg(T data, typename L4::Types::Enable_if<sizeof(T) <= sizeof(char const *), bool>::type = true)
222 { set_direct_value<T>(data); }
223};
224
225
226template<typename T>
227class Varg_t : public Varg
228{
229public:
230 typedef typename Va_type<T>::Value Value;
231 explicit Varg_t(Value v) : Varg()
232 { _data = v; set_value<T>(Va_type<T>::addr_of(_data)); }
233
234private:
235 Value _data;
236};
237
238template<unsigned MAX = L4_UTCB_GENERIC_DATA_SIZE>
239class Varg_list;
240
253{
254private:
255 template<unsigned T>
256 friend class Varg_list;
257
259 class Iter_state
260 {
261 private:
262 using M = l4_umword_t;
263 using Mp = M const *;
264 Mp _c;
265 Mp _e;
266
268 Mp next_arg(Varg const &a) const
269 {
270 return _c + 1 + (Msg::align_to<M>(a.length()) / sizeof(M));
271 }
272
273 public:
275 Iter_state() : _c(nullptr) {}
276
278 Iter_state(Mp c, Mp e) : _c(c), _e(e)
279 {}
280
282 bool valid() const
283 { return _c && _c < _e; }
284
286 Mp begin() const { return _c; }
287
289 Mp end() const { return _e; }
290
295 Varg pop()
296 {
297 if (!valid())
298 return Varg::nil();
299
300 Varg a;
301 a.tag(_c[0]);
302 a.data(reinterpret_cast<char const *>(&_c[1]));
303 _c = next_arg(a);
304 if (_c > _e)
305 return Varg::nil();
306
307 return a;
308 }
309
311 bool operator == (Iter_state const &o) const
312 { return _c == o._c; }
313
315 bool operator != (Iter_state const &o) const
316 { return _c != o._c; }
317 };
318
319 Iter_state _s;
320
321public:
323 Varg_list_ref() = default;
324
331 Varg_list_ref(void const *start, void const *end)
332 : _s(reinterpret_cast<l4_umword_t const *>(start),
333 reinterpret_cast<l4_umword_t const *>(end))
334 {}
335
338 {
339 private:
340 Iter_state _s;
341 Varg _a;
342
343 public:
345 Iterator(Iter_state const &s)
346 : _s(s)
347 {
348 _a = _s.pop();
349 }
350
352 explicit operator bool () const
353 { return !_a.is_nil(); }
354
357 {
358 if (!_a.is_nil())
359 _a = _s.pop();
360
361 return *this;
362 }
363
366 { return _a; }
367
369 bool equals(Iterator const &o) const
370 {
371 if (_a.is_nil() && o._a.is_nil())
372 return true;
373
374 return _s == o._s;
375 }
376
377 bool operator == (Iterator const &o) const
378 { return equals(o); }
379
380 bool operator != (Iterator const &o) const
381 { return !equals(o); }
382 };
383
386 { return _s.pop(); }
387
390 L4_DEPRECATED("Use range for or pop_front.")
391 { return _s.pop(); }
392
395 { return Iterator(_s); }
396
398 Iterator end() const
399 { return Iterator(Iter_state()); }
400};
401
409template<unsigned MAX>
411{
412 l4_umword_t data[MAX];
413 Varg_list(Varg_list const &);
414
415public:
418 {
419 if (!r._s.valid())
420 return;
421
422 l4_umword_t const *rs = r._s.begin();
423 unsigned c = r._s.end() - rs;
424 for (unsigned i = 0; i < c; ++i)
425 data[i] = rs[i];
426
427 this->_s = Iter_state(data, data + c);
428 }
429};
430
431
432namespace Msg {
433template<> struct Elem<Varg const *>
434{
435 typedef Varg const *arg_type;
436 typedef Varg_list_ref svr_type;
437 typedef Varg_list_ref svr_arg_type;
438 enum { Is_optional = false };
439};
440
441template<> struct Is_valid_rpc_type<Varg> : L4::Types::False {};
442template<> struct Is_valid_rpc_type<Varg *> : L4::Types::False {};
443template<> struct Is_valid_rpc_type<Varg &> : L4::Types::False {};
444template<> struct Is_valid_rpc_type<Varg const &> : L4::Types::False {};
445
446template<> struct Direction<Varg const *> : Dir_in {};
447template<> struct Class<Varg const *> : Cls_data {};
448
449template<typename DIR, typename CLASS>
450struct Clnt_val_ops<Varg, DIR, CLASS>;
451
452template<>
453struct Clnt_val_ops<Varg, Dir_in, Cls_data> :
454 Clnt_noops<Varg const &>
455{
456 using Clnt_noops<Varg const &>::to_msg;
457 static int to_msg(char *msg, unsigned offs, unsigned limit,
458 Varg const &a, Dir_in, Cls_data)
459 {
460 for (Varg const *i = &a; i->tag(); ++i)
461 {
462 offs = align_to<l4_umword_t>(offs);
463 if (L4_UNLIKELY(!check_size<l4_umword_t>(offs, limit)))
464 return -L4_EMSGTOOLONG;
465 *reinterpret_cast<l4_umword_t*>(msg + offs) = i->tag();
466 offs += sizeof(l4_umword_t);
467 if (L4_UNLIKELY(!check_size<char>(offs, limit, i->length())))
468 return -L4_EMSGTOOLONG;
469 char const *d = i->data();
470 for (unsigned x = 0; x < i->length(); ++x)
471 msg[offs++] = *d++;
472 }
473
474 return offs;
475 }
476};
477
478template<>
479struct Svr_val_ops<Varg_list_ref, Dir_in, Cls_data> :
480 Svr_noops<Varg_list_ref>
481{
482 using Svr_noops<Varg_list_ref>::to_svr;
483 static int to_svr(char *msg, unsigned offset, unsigned limit,
484 Varg_list_ref &a, Dir_in, Cls_data)
485 {
486 unsigned start = align_to<l4_umword_t>(offset);
487 unsigned offs;
488 for (offs = start; offs < limit;)
489 {
490 unsigned noffs = align_to<l4_umword_t>(offs);
491 if (L4_UNLIKELY(!check_size<l4_umword_t>(noffs, limit)))
492 break;
493
494 offs = noffs;
495 Varg arg;
496 arg.tag(*reinterpret_cast<l4_umword_t*>(msg + offs));
497
498 if (!arg.tag())
499 break;
500
501 offs += sizeof(l4_umword_t);
502
503 if (L4_UNLIKELY(!check_size<char>(offs, limit, arg.length())))
504 return -L4_EMSGTOOLONG;
505 offs += arg.length();
506 }
507
508 a = Varg_list_ref(msg + start, msg + align_to<l4_umword_t>(offs));
509 return offs;
510 }
511};
512}
513}}
Iterator for Valists.
Definition ipc_varg:338
Iterator(Iter_state const &s)
Create a new iterator.
Definition ipc_varg:345
bool equals(Iterator const &o) const
check for equality
Definition ipc_varg:369
Iterator & operator++()
increment iterator to the next arg
Definition ipc_varg:356
Varg operator*() const
dereference the iterator, get Varg
Definition ipc_varg:365
List of variable-sized RPC parameters as received by the server.
Definition ipc_varg:253
Iterator begin() const
Returns an interator to the first Varg.
Definition ipc_varg:394
Varg pop_front()
Get the next parameter in the list.
Definition ipc_varg:385
Varg next()
Get the next parameter in the list.
Definition ipc_varg:389
Varg_list_ref(void const *start, void const *end)
Create a parameter list over a given memory region.
Definition ipc_varg:331
Iterator end() const
Returns the end of the list.
Definition ipc_varg:398
Varg_list_ref()=default
Create an empty parameter list.
Self-contained list of variable-sized RPC parameters.
Definition ipc_varg:411
Varg_list(Varg_list_ref const &r)
Create a parameter list as a copy from a referencing list.
Definition ipc_varg:417
Variably sized RPC argument.
Definition ipc_varg:97
bool is_of_int() const
Definition ipc_varg:174
Varg(char const *data)
Make Varg from null-terminated string.
Definition ipc_varg:217
char const * data() const
Definition ipc_varg:123
Varg(L4_varg_type t, void const *v, int len)
Make an indirect varg.
Definition ipc_varg:141
Varg()=default
Make uninitialized Varg.
l4_umword_t Tag
The data type for the tag.
Definition ipc_varg:106
Va_type< V >::Ret_value value() const
Definition ipc_varg:154
bool is_of() const
Definition ipc_varg:168
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:204
unsigned length() const
Get the size of the RPC argument.
Definition ipc_varg:114
void set_value(void const *d)
Set to indirect value of type T.
Definition ipc_varg:195
Tag tag() const
Definition ipc_varg:116
L4_varg_type type() const
Definition ipc_varg:109
void tag(Tag tag)
Set Varg tag (usually from message)
Definition ipc_varg:118
Varg(T const *data)
Make Varg from indirect value (pointer)
Definition ipc_varg:215
Varg(T data, typename L4::Types::Enable_if< sizeof(T)<=sizeof(char const *), bool >::type=true)
Make Varg from direct value.
Definition ipc_varg:221
void data(char const *d)
Set Varg to indirect data value (usually in UTCB)
Definition ipc_varg:120
bool is_nil() const
Definition ipc_varg:171
bool get_value(typename Va_type< T >::Value *v) const
Get the value of the Varg as type T.
Definition ipc_varg:184
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:67
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:285
#define L4_EXPORT
Attribute to mark functions, variables, and data types as being exported from a library.
Definition compiler.h:221
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition compiler.h:290
L4 low-level kernel interface.
False meta value.
Definition types:308
L4 flexpage type.
Definition __l4_fpage.h:85