L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ipc_basics
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 <l4/sys/utcb.h>
11#include <l4/sys/err.h>
12
13namespace L4 {
14
16namespace Ipc {
17
19namespace Msg {
20
21using L4::Types::True;
23
30constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
31{ return (bytes + align - 1) & ~(align - 1); }
32
39template<typename T>
40constexpr unsigned long align_to(unsigned long bytes) noexcept
41{ return align_to(bytes, __alignof(T)); }
42
52template<typename T>
53constexpr bool check_size(unsigned offset, unsigned limit) noexcept
54{
55 return offset + sizeof(T) <= limit;
56}
57
70template<typename T, typename CTYPE>
71inline bool check_size(unsigned offset, unsigned limit, CTYPE cnt) noexcept
72{
73 if (L4_UNLIKELY(sizeof(CTYPE) <= sizeof(unsigned) &&
74 ~0U / sizeof(T) <= static_cast<unsigned>(cnt)))
75 return false;
76
77 if (L4_UNLIKELY(sizeof(CTYPE) > sizeof(unsigned) &&
78 static_cast<CTYPE>(~0U / sizeof(T)) <= cnt))
79 return false;
80
81 return sizeof(T) * cnt <= limit - offset;
82}
83
84
85enum
86{
94 Mr_words = L4_UTCB_GENERIC_DATA_SIZE,
98 Br_bytes = Word_bytes * L4_UTCB_GENERIC_BUFFERS_SIZE,
99};
100
101
113template<typename T>
114inline int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
115{
116 offs = align_to<T>(offs);
117 if (L4_UNLIKELY(!check_size<T>(offs, limit)))
118 return -L4_EMSGTOOLONG;
119 *reinterpret_cast<typename L4::Types::Remove_const<T>::type *>(msg + offs) = v;
120 return offs + sizeof(T);
121}
122
134template<typename T>
135inline int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
136{
137 offs = align_to<T>(offs);
138 if (L4_UNLIKELY(!check_size<T>(offs, limit)))
139 return -L4_EMSGTOOSHORT;
140 v = *reinterpret_cast<T *>(msg + offs);
141 return offs + sizeof(T);
142}
143
145struct Dir_in { typedef Dir_in type; typedef Dir_in dir; };
147struct Dir_out { typedef Dir_out type; typedef Dir_out dir; };
148
150struct Cls_data { typedef Cls_data type; typedef Cls_data cls; };
152struct Cls_item { typedef Cls_item type; typedef Cls_item cls; };
154struct Cls_buffer { typedef Cls_buffer type; typedef Cls_buffer cls; };
155
156// Typical combinations
167
168// implementation details
169namespace Detail {
170
171template<typename T> struct _Plain
172{
173 typedef T type;
174 static T deref(T v) noexcept { return v; }
175};
176
177template<typename T> struct _Plain<T *>
178{
179 typedef T type;
180 static T &deref(T *v) noexcept { return *v; }
181};
182
183template<typename T> struct _Plain<T &>
184{
185 typedef T type;
186 static T &deref(T &v) noexcept { return v; }
187
188};
189
190template<typename T> struct _Plain<T const &>
191{
192 typedef T type;
193 static T const &deref(T const &v) noexcept { return v; }
194};
195
196template<typename T> struct _Plain<T const *>
197{
198 typedef T type;
199 static T const &deref(T const *v) noexcept { return *v; }
200};
201}
202
210template<typename MTYPE, typename DIR, typename CLASS> struct Clnt_val_ops;
211
212template<typename T> struct Clnt_noops
213{
214 template<typename A, typename B>
215 static constexpr int to_msg(char *, unsigned offset, unsigned, T, A, B) noexcept
216 { return offset; }
217
219 template<typename A, typename B>
220 static constexpr int from_msg(char *, unsigned offset, unsigned, long, T const &, A, B) noexcept
221 { return offset; }
222};
223
224template<typename T> struct Svr_noops
225{
226 template<typename A, typename B>
227 static constexpr int from_svr(char *, unsigned offset, unsigned, long, T, A, B) noexcept
228 { return offset; }
229
231 template<typename A, typename B>
232 static constexpr int to_svr(char *, unsigned offset, unsigned, T, A, B) noexcept
233 { return offset; }
234};
235
236template<typename MTYPE, typename CLASS>
237struct Clnt_val_ops<MTYPE, Dir_in, CLASS> : Clnt_noops<MTYPE>
238{
239 using Clnt_noops<MTYPE>::to_msg;
241 static int to_msg(char *msg, unsigned offset, unsigned limit,
242 MTYPE arg, Dir_in, CLASS) noexcept
243 { return msg_add<MTYPE>(msg, offset, limit, arg); }
244};
245
246
247template<typename MTYPE, typename CLASS>
248struct Clnt_val_ops<MTYPE, Dir_out, CLASS> : Clnt_noops<MTYPE>
249{
250 using Clnt_noops<MTYPE>::from_msg;
252 static int from_msg(char *msg, unsigned offset, unsigned limit, long,
253 MTYPE &arg, Dir_out, CLASS) noexcept
254 { return msg_get<MTYPE>(msg, offset, limit, arg); }
255};
256
264template<typename MTYPE, typename DIR, typename CLASS> struct Svr_val_ops;
265
266template<typename MTYPE, typename CLASS>
267struct Svr_val_ops<MTYPE, Dir_in, CLASS> : Svr_noops<MTYPE>
268{
269 using Svr_noops<MTYPE>::to_svr;
271 static int to_svr(char *msg, unsigned offset, unsigned limit,
272 MTYPE &arg, Dir_in, CLASS) noexcept
273 { return msg_get<MTYPE>(msg, offset, limit, arg); }
274};
275
276template<typename MTYPE, typename CLASS>
277struct Svr_val_ops<MTYPE, Dir_out, CLASS> : Svr_noops<MTYPE>
278{
279 using Svr_noops<MTYPE>::to_svr;
280 static int to_svr(char *, unsigned offs, unsigned limit,
281 MTYPE &, Dir_out, CLASS) noexcept
282 {
283 offs = align_to<MTYPE>(offs);
284 if (L4_UNLIKELY(!check_size<MTYPE>(offs, limit)))
285 return -L4_EMSGTOOLONG;
286 return offs + sizeof(MTYPE);
287 }
288
289 using Svr_noops<MTYPE>::from_svr;
291 static int from_svr(char *msg, unsigned offset, unsigned limit, long,
292 MTYPE arg, Dir_out, CLASS) noexcept
293 { return msg_add<MTYPE>(msg, offset, limit, arg); }
294};
295
296template<typename T> struct Elem
297{
299 typedef T arg_type;
301 typedef T svr_type;
303 typedef T svr_arg_type; // might by const & (depending on the size)
304
305 enum { Is_optional = false };
306
307};
308
309template<typename T> struct Elem<T &>
310{
311 typedef T &arg_type;
312 typedef T svr_type;
314 typedef T &svr_arg_type;
315 enum { Is_optional = false };
316};
317
318template<typename T> struct Elem<T const &>
319{
320 typedef T const &arg_type;
321 typedef T svr_type;
322 // as the RPC uses a const reference we use it here too,
323 // we could also use pass by value depending on the size
324 typedef T const &svr_arg_type;
325 enum { Is_optional = false };
326};
327
328template<typename T> struct Elem<T *> : Elem<T &>
329{
330 typedef T *arg_type;
331};
332
333template<typename T> struct Elem<T const *> : Elem<T const &>
334{
335 typedef T const *arg_type;
336};
337
339template<typename T> struct Is_valid_rpc_type : L4::Types::True {};
340
341// Static assertions outside functions work only properly from C++11
342// onewards. On earlier version make sure the compiler fails on an ugly
343// undefined struct instead.
344template<typename T, bool B> struct Error_invalid_rpc_parameter_used;
345template<typename T> struct Error_invalid_rpc_parameter_used<T, true> {};
346
347#if __cplusplus >= 201103L
348template<typename T>
349struct _Elem : Elem<T>
350{
351 static_assert(Is_valid_rpc_type<T>::value,
352 "L4::Ipc::Msg::_Elem<T>: type T is not a valid RPC parameter type.");
353};
354#else
355template<typename T>
356struct _Elem : Elem<T>,
357 Error_invalid_rpc_parameter_used<T, Is_valid_rpc_type<T>::value>
358{};
359#endif
360
361
362template<typename T> struct Class : Cls_data {};
363template<typename T> struct Direction : Dir_in {};
364template<typename T> struct Direction<T const &> : Dir_in {};
365template<typename T> struct Direction<T const *> : Dir_in {};
366template<typename T> struct Direction<T &> : Dir_out {};
367template<typename T> struct Direction<T *> : Dir_out {};
368
369template<typename T> struct _Clnt_noops :
370 Clnt_noops<typename Detail::_Plain<typename _Elem<T>::arg_type>::type>
371{};
372
373namespace Detail {
374
375template<typename T, typename DIR, typename CLASS>
376struct _Clnt_val_ops :
377 Clnt_val_ops<typename Detail::_Plain<T>::type, DIR, CLASS> {};
378
379template<typename T,
380 typename ELEM = _Elem<T>,
381 typename CLNT_OPS = _Clnt_val_ops<typename ELEM::arg_type,
382 typename Direction<T>::type,
383 typename Class<typename Detail::_Plain<T>::type>::type>
384 >
385struct _Clnt_xmit : CLNT_OPS {};
386
387template<typename T,
388 typename ELEM = _Elem<T>,
389 typename SVR_OPS = Svr_val_ops<typename ELEM::svr_type,
390 typename Direction<T>::type,
391 typename Class<typename Detail::_Plain<T>::type>::type>
392 >
393struct _Svr_xmit : SVR_OPS {};
394
395} //namespace Detail
396template<typename T> struct Clnt_xmit : Detail::_Clnt_xmit<T> {};
397template<typename T> struct Svr_xmit : Detail::_Svr_xmit<T> {};
398
399}}} // namespace Msg, Ipc, L4
400
401
Error codes.
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:57
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:56
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:275
constexpr bool check_size(unsigned offset, unsigned limit) noexcept
Check if there is enough space for T from offset to limit.
Definition ipc_basics:53
constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
Pad bytes to the given alignment align (in bytes)
Definition ipc_basics:30
@ Br_bytes
number of bytes available in the UTCB buffer registers
Definition ipc_basics:98
@ Item_words
number of message words for one message item
Definition ipc_basics:90
@ Mr_bytes
number of bytes available in the UTCB message registers
Definition ipc_basics:96
@ Item_bytes
number of bytes for one message item
Definition ipc_basics:92
@ Word_bytes
number of bytes for one message word
Definition ipc_basics:88
@ Mr_words
number of message words available in the UTCB
Definition ipc_basics:94
int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
Add some data to a message at offs.
Definition ipc_basics:114
int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
Get some data from a message at offs.
Definition ipc_basics:135
L4 low-level kernel interface.
Defines client-side handling of ‘MTYPE’ as RPC argument.
Definition ipc_basics:210
Marker type for receive buffer values.
Definition ipc_basics:154
Marker type for data values.
Definition ipc_basics:150
Marker type for item values.
Definition ipc_basics:152
Marker type for input values.
Definition ipc_basics:145
Marker type for output values.
Definition ipc_basics:147
Marker for Input data.
Definition ipc_basics:158
Marker for Input items.
Definition ipc_basics:162
Marker for Output data.
Definition ipc_basics:160
Marker for Output items.
Definition ipc_basics:164
Marker for receive buffers.
Definition ipc_basics:166
Type trait defining a valid RPC parameter type.
Definition ipc_basics:339
Defines server-side handling for MTYPE server arguments.
Definition ipc_basics:264
False meta value.
Definition types:296
True meta value.
Definition types:300