L4Re Operating System Framework – Interface and Usage Documentation
Loading...
Searching...
No Matches
ipc_basics
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 <l4/sys/utcb.h>
22#include <l4/sys/err.h>
23
24namespace L4 {
25
27namespace Ipc {
28
30namespace Msg {
31
32using L4::Types::True;
34
41constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
42{ return (bytes + align - 1) & ~(align - 1); }
43
50template<typename T>
51constexpr unsigned long align_to(unsigned long bytes) noexcept
52{ return align_to(bytes, __alignof(T)); }
53
63template<typename T>
64constexpr bool check_size(unsigned offset, unsigned limit) noexcept
65{
66 return offset + sizeof(T) <= limit;
67}
68
81template<typename T, typename CTYPE>
82inline bool check_size(unsigned offset, unsigned limit, CTYPE cnt) noexcept
83{
84 if (L4_UNLIKELY(sizeof(CTYPE) <= sizeof(unsigned) &&
85 ~0U / sizeof(T) <= static_cast<unsigned>(cnt)))
86 return false;
87
88 if (L4_UNLIKELY(sizeof(CTYPE) > sizeof(unsigned) &&
89 static_cast<CTYPE>(~0U / sizeof(T)) <= cnt))
90 return false;
91
92 return sizeof(T) * cnt <= limit - offset;
93}
94
95
96enum
97{
105 Mr_words = L4_UTCB_GENERIC_DATA_SIZE,
109 Br_bytes = Word_bytes * L4_UTCB_GENERIC_BUFFERS_SIZE,
110};
111
112
124template<typename T>
125inline int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
126{
127 offs = align_to<T>(offs);
128 if (L4_UNLIKELY(!check_size<T>(offs, limit)))
129 return -L4_EMSGTOOLONG;
130 *reinterpret_cast<typename L4::Types::Remove_const<T>::type *>(msg + offs) = v;
131 return offs + sizeof(T);
132}
133
145template<typename T>
146inline int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
147{
148 offs = align_to<T>(offs);
149 if (L4_UNLIKELY(!check_size<T>(offs, limit)))
150 return -L4_EMSGTOOSHORT;
151 v = *reinterpret_cast<T *>(msg + offs);
152 return offs + sizeof(T);
153}
154
156struct Dir_in { typedef Dir_in type; typedef Dir_in dir; };
158struct Dir_out { typedef Dir_out type; typedef Dir_out dir; };
159
161struct Cls_data { typedef Cls_data type; typedef Cls_data cls; };
163struct Cls_item { typedef Cls_item type; typedef Cls_item cls; };
165struct Cls_buffer { typedef Cls_buffer type; typedef Cls_buffer cls; };
166
167// Typical combinations
178
179// implementation details
180namespace Detail {
181
182template<typename T> struct _Plain
183{
184 typedef T type;
185 static T deref(T v) noexcept { return v; }
186};
187
188template<typename T> struct _Plain<T *>
189{
190 typedef T type;
191 static T &deref(T *v) noexcept { return *v; }
192};
193
194template<typename T> struct _Plain<T &>
195{
196 typedef T type;
197 static T &deref(T &v) noexcept { return v; }
198
199};
200
201template<typename T> struct _Plain<T const &>
202{
203 typedef T type;
204 static T const &deref(T const &v) noexcept { return v; }
205};
206
207template<typename T> struct _Plain<T const *>
208{
209 typedef T type;
210 static T const &deref(T const *v) noexcept { return *v; }
211};
212}
213
221template<typename MTYPE, typename DIR, typename CLASS> struct Clnt_val_ops;
222
223template<typename T> struct Clnt_noops
224{
225 template<typename A, typename B>
226 static constexpr int to_msg(char *, unsigned offset, unsigned, T, A, B) noexcept
227 { return offset; }
228
230 template<typename A, typename B>
231 static constexpr int from_msg(char *, unsigned offset, unsigned, long, T const &, A, B) noexcept
232 { return offset; }
233};
234
235template<typename T> struct Svr_noops
236{
237 template<typename A, typename B>
238 static constexpr int from_svr(char *, unsigned offset, unsigned, long, T, A, B) noexcept
239 { return offset; }
240
242 template<typename A, typename B>
243 static constexpr int to_svr(char *, unsigned offset, unsigned, T, A, B) noexcept
244 { return offset; }
245};
246
247template<typename MTYPE, typename CLASS>
248struct Clnt_val_ops<MTYPE, Dir_in, CLASS> : Clnt_noops<MTYPE>
249{
250 using Clnt_noops<MTYPE>::to_msg;
252 static int to_msg(char *msg, unsigned offset, unsigned limit,
253 MTYPE arg, Dir_in, CLASS) noexcept
254 { return msg_add<MTYPE>(msg, offset, limit, arg); }
255};
256
257
258template<typename MTYPE, typename CLASS>
259struct Clnt_val_ops<MTYPE, Dir_out, CLASS> : Clnt_noops<MTYPE>
260{
261 using Clnt_noops<MTYPE>::from_msg;
263 static int from_msg(char *msg, unsigned offset, unsigned limit, long,
264 MTYPE &arg, Dir_out, CLASS) noexcept
265 { return msg_get<MTYPE>(msg, offset, limit, arg); }
266};
267
275template<typename MTYPE, typename DIR, typename CLASS> struct Svr_val_ops;
276
277template<typename MTYPE, typename CLASS>
278struct Svr_val_ops<MTYPE, Dir_in, CLASS> : Svr_noops<MTYPE>
279{
280 using Svr_noops<MTYPE>::to_svr;
282 static int to_svr(char *msg, unsigned offset, unsigned limit,
283 MTYPE &arg, Dir_in, CLASS) noexcept
284 { return msg_get<MTYPE>(msg, offset, limit, arg); }
285};
286
287template<typename MTYPE, typename CLASS>
288struct Svr_val_ops<MTYPE, Dir_out, CLASS> : Svr_noops<MTYPE>
289{
290 using Svr_noops<MTYPE>::to_svr;
291 static int to_svr(char *, unsigned offs, unsigned limit,
292 MTYPE &, Dir_out, CLASS) noexcept
293 {
294 offs = align_to<MTYPE>(offs);
295 if (L4_UNLIKELY(!check_size<MTYPE>(offs, limit)))
296 return -L4_EMSGTOOLONG;
297 return offs + sizeof(MTYPE);
298 }
299
300 using Svr_noops<MTYPE>::from_svr;
302 static int from_svr(char *msg, unsigned offset, unsigned limit, long,
303 MTYPE arg, Dir_out, CLASS) noexcept
304 { return msg_add<MTYPE>(msg, offset, limit, arg); }
305};
306
307template<typename T> struct Elem
308{
310 typedef T arg_type;
312 typedef T svr_type;
314 typedef T svr_arg_type; // might by const & (depending on the size)
315
316 enum { Is_optional = false };
317
318};
319
320template<typename T> struct Elem<T &>
321{
322 typedef T &arg_type;
323 typedef T svr_type;
325 typedef T &svr_arg_type;
326 enum { Is_optional = false };
327};
328
329template<typename T> struct Elem<T const &>
330{
331 typedef T const &arg_type;
332 typedef T svr_type;
333 // as the RPC uses a const reference we use it here too,
334 // we could also use pass by value depending on the size
335 typedef T const &svr_arg_type;
336 enum { Is_optional = false };
337};
338
339template<typename T> struct Elem<T *> : Elem<T &>
340{
341 typedef T *arg_type;
342};
343
344template<typename T> struct Elem<T const *> : Elem<T const &>
345{
346 typedef T const *arg_type;
347};
348
350template<typename T> struct Is_valid_rpc_type : L4::Types::True {};
351
352// Static assertions outside functions work only properly from C++11
353// onewards. On earlier version make sure the compiler fails on an ugly
354// undefined struct instead.
355template<typename T, bool B> struct Error_invalid_rpc_parameter_used;
356template<typename T> struct Error_invalid_rpc_parameter_used<T, true> {};
357
358#if __cplusplus >= 201103L
359template<typename T>
360struct _Elem : Elem<T>
361{
362 static_assert(Is_valid_rpc_type<T>::value,
363 "L4::Ipc::Msg::_Elem<T>: type T is not a valid RPC parameter type.");
364};
365#else
366template<typename T>
367struct _Elem : Elem<T>,
368 Error_invalid_rpc_parameter_used<T, Is_valid_rpc_type<T>::value>
369{};
370#endif
371
372
373template<typename T> struct Class : Cls_data {};
374template<typename T> struct Direction : Dir_in {};
375template<typename T> struct Direction<T const &> : Dir_in {};
376template<typename T> struct Direction<T const *> : Dir_in {};
377template<typename T> struct Direction<T &> : Dir_out {};
378template<typename T> struct Direction<T *> : Dir_out {};
379
380template<typename T> struct _Clnt_noops :
381 Clnt_noops<typename Detail::_Plain<typename _Elem<T>::arg_type>::type>
382{};
383
384namespace Detail {
385
386template<typename T, typename DIR, typename CLASS>
387struct _Clnt_val_ops :
388 Clnt_val_ops<typename Detail::_Plain<T>::type, DIR, CLASS> {};
389
390template<typename T,
391 typename ELEM = _Elem<T>,
392 typename CLNT_OPS = _Clnt_val_ops<typename ELEM::arg_type,
393 typename Direction<T>::type,
394 typename Class<typename Detail::_Plain<T>::type>::type>
395 >
396struct _Clnt_xmit : CLNT_OPS {};
397
398template<typename T,
399 typename ELEM = _Elem<T>,
400 typename SVR_OPS = Svr_val_ops<typename ELEM::svr_type,
401 typename Direction<T>::type,
402 typename Class<typename Detail::_Plain<T>::type>::type>
403 >
404struct _Svr_xmit : SVR_OPS {};
405
406} //namespace Detail
407template<typename T> struct Clnt_xmit : Detail::_Clnt_xmit<T> {};
408template<typename T> struct Svr_xmit : Detail::_Svr_xmit<T> {};
409
410}}} // namespace Msg, Ipc, L4
411
412
Error codes.
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:51
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:67
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:66
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:285
constexpr bool check_size(unsigned offset, unsigned limit) noexcept
Check if there is enough space for T from offset to limit.
Definition ipc_basics:64
constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
Pad bytes to the given alignment align (in bytes)
Definition ipc_basics:41
int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
Add some data to a message at offs.
Definition ipc_basics:125
int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
Get some data from a message at offs.
Definition ipc_basics:146
@ Br_bytes
number of bytes available in the UTCB buffer registers
Definition ipc_basics:109
@ Item_words
number of message words for one message item
Definition ipc_basics:101
@ Mr_bytes
number of bytes available in the UTCB message registers
Definition ipc_basics:107
@ Item_bytes
number of bytes for one message item
Definition ipc_basics:103
@ Word_bytes
number of bytes for one message word
Definition ipc_basics:99
@ Mr_words
number of message words available in the UTCB
Definition ipc_basics:105
L4 low-level kernel interface.
Defines client-side handling of ‘MTYPE’ as RPC argument.
Definition ipc_basics:221
Marker type for receive buffer values.
Definition ipc_basics:165
Marker type for data values.
Definition ipc_basics:161
Marker type for item values.
Definition ipc_basics:163
Marker type for input values.
Definition ipc_basics:156
Marker type for output values.
Definition ipc_basics:158
Marker for Input data.
Definition ipc_basics:169
Marker for Input items.
Definition ipc_basics:173
Marker for Output data.
Definition ipc_basics:171
Marker for Output items.
Definition ipc_basics:175
Marker for receive buffers.
Definition ipc_basics:177
Type trait defining a valid RPC parameter type.
Definition ipc_basics:350
Defines server-side handling for MTYPE server arguments.
Definition ipc_basics:275
False meta value.
Definition types:308
True meta value.
Definition types:312