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 * 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;
22using L4::Types::False;
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<L4::Types::Remove_const_t<T> *>(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 { using type = Dir_in; using dir = Dir_in; };
147struct Dir_out { using type = Dir_out; using dir = Dir_out; };
148
150struct Cls_data { using type = Cls_data; using cls = Cls_data; };
152struct Cls_item { using type = Cls_item; using cls = Cls_item; };
154struct Cls_buffer { using type = Cls_buffer; using cls = Cls_buffer; };
155
156// Typical combinations
167
168// implementation details
169namespace Detail {
170
171template<typename T> struct _Plain
172{
173 using type = T;
174 static T deref(T v) noexcept { return v; }
175};
176
177template<typename T> struct _Plain<T *>
178{
179 using type = T;
180 static T &deref(T *v) noexcept { return *v; }
181};
182
183template<typename T> struct _Plain<T &>
184{
185 using type = T;
186 static T &deref(T &v) noexcept { return v; }
187
188};
189
190template<typename T> struct _Plain<T const &>
191{
192 using type = T;
193 static T const &deref(T const &v) noexcept { return v; }
194};
195
196template<typename T> struct _Plain<T const *>
197{
198 using type = T;
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
212// Provides empty default implementations for the Dir/Cls combinations in which
213// the type does not participate (for the Do_in_items, Do_in_data, ... passes in
214// Rpc_inline_call::call).
215//
216// The Clnt_val_ops specializations derive from Clnt_noops, and pull in the
217// empty default implementations with `using Clnt_noops::{to,from}_msg`, to
218// handle the other Dir/Cls combinations.
219template<typename T> struct Clnt_noops
220{
221 template<typename A, typename B>
222 static constexpr int to_msg(char *, unsigned offset, unsigned, T, A, B) noexcept
223 { return offset; }
224
226 template<typename A, typename B>
227 static constexpr int from_msg(char *, unsigned offset, unsigned, long, T const &, A, B) noexcept
228 { return offset; }
229};
230
231// Provides empty default implementations for the Dir/Class combinations in which
232// the type does not participate (for the Do_in_items, Do_in_data, ... passes in
233// handle_svr_obj_call).
234//
235// The Svr_val_ops specializations derive from Svr_noops, and pull in the
236// empty default implementations with `using Svr_noops::{from,to}_svr`, to
237// handle the other Dir/Cls combinations.
238template<typename T> struct Svr_noops
239{
240 template<typename A, typename B>
241 static constexpr int from_svr(char *, unsigned offset, unsigned, long, T, A, B) noexcept
242 { return offset; }
243
245 template<typename A, typename B>
246 static constexpr int to_svr(char *, unsigned offset, unsigned, T const &, A, B) noexcept
247 { return offset; }
248};
249
250// Default implementation, via reinterpret_cast.
251// Override by partially specializing Clnt_val_ops.
252template<typename MTYPE, typename CLASS>
253struct Clnt_val_ops<MTYPE, Dir_in, CLASS> : Clnt_noops<MTYPE>
254{
255 using Clnt_noops<MTYPE>::to_msg;
257 static int to_msg(char *msg, unsigned offset, unsigned limit,
258 MTYPE arg, Dir_in, CLASS) noexcept
259 { return msg_add<MTYPE>(msg, offset, limit, arg); }
260};
261
262// Default implementation, via reinterpret_cast.
263// Override by partially specializing Clnt_val_ops.
264template<typename MTYPE, typename CLASS>
265struct Clnt_val_ops<MTYPE, Dir_out, CLASS> : Clnt_noops<MTYPE>
266{
267 using Clnt_noops<MTYPE>::from_msg;
269 static int from_msg(char *msg, unsigned offset, unsigned limit, long,
270 MTYPE &arg, Dir_out, CLASS) noexcept
271 { return msg_get<MTYPE>(msg, offset, limit, arg); }
272};
273
281template<typename MTYPE, typename DIR, typename CLASS> struct Svr_val_ops;
282
283// Default implementation, via reinterpret_cast.
284// Override by partially specializing Clnt_val_ops.
285template<typename MTYPE, typename CLASS>
286struct Svr_val_ops<MTYPE, Dir_in, CLASS> : Svr_noops<MTYPE>
287{
288 using Svr_noops<MTYPE>::to_svr;
290 static int to_svr(char *msg, unsigned offset, unsigned limit,
291 MTYPE &arg, Dir_in, CLASS) noexcept
292 { return msg_get<MTYPE>(msg, offset, limit, arg); }
293};
294
295// Default implementation, via reinterpret_cast.
296// Override by partially specializing Clnt_val_ops.
297template<typename MTYPE, typename CLASS>
298struct Svr_val_ops<MTYPE, Dir_out, CLASS> : Svr_noops<MTYPE>
299{
301 using Svr_noops<MTYPE>::to_svr;
302 static int to_svr(char *, unsigned offs, unsigned limit,
303 MTYPE &, Dir_out, CLASS) noexcept
304 {
305 offs = align_to<MTYPE>(offs);
306 if (L4_UNLIKELY(!check_size<MTYPE>(offs, limit)))
307 return -L4_EMSGTOOLONG;
308 return offs + sizeof(MTYPE);
309 }
310
311 using Svr_noops<MTYPE>::from_svr;
313 static int from_svr(char *msg, unsigned offset, unsigned limit, long,
314 MTYPE arg, Dir_out, CLASS) noexcept
315 { return msg_add<MTYPE>(msg, offset, limit, arg); }
316};
317
318template<typename T> struct Elem
319{
321 using arg_type = T;
323 using svr_type = T;
325 using svr_arg_type = T; // might be const & (depending on the size)
326
327 enum { Is_optional = false };
328
329};
330
331template<typename T> struct Elem<T &>
332{
333 using arg_type = T &;
334 using svr_type = T;
336 using svr_arg_type = T &;
337 enum { Is_optional = false };
338};
339
340template<typename T> struct Elem<T const &>
341{
342 using arg_type = T const &;
343 using svr_type = T;
344 // as the RPC uses a const reference we use it here too,
345 // we could also use pass by value depending on the size
346 using svr_arg_type = T const &;
347 enum { Is_optional = false };
348};
349
350template<typename T> struct Elem<T *> : Elem<T &>
351{
352 using arg_type = T *;
353};
354
355template<typename T> struct Elem<T const *> : Elem<T const &>
356{
357 using arg_type = T const *;
358};
359
361template<typename T> struct Is_valid_rpc_type : L4::Types::True {};
362
363// Static assertions outside functions work only properly from C++11
364// onwards. On earlier version make sure the compiler fails on an ugly
365// undefined struct instead.
366template<typename T, bool B> struct Error_invalid_rpc_parameter_used;
367template<typename T> struct Error_invalid_rpc_parameter_used<T, true> {};
368
369#if __cplusplus >= 201103L
370template<typename T>
371struct _Elem : Elem<T>
372{
373 static_assert(Is_valid_rpc_type<T>::value,
374 "L4::Ipc::Msg::_Elem<T>: type T is not a valid RPC parameter type.");
375};
376#else
377template<typename T>
378struct _Elem : Elem<T>,
379 Error_invalid_rpc_parameter_used<T, Is_valid_rpc_type<T>::value>
380{};
381#endif
382
383
384template<typename T> struct Class : Cls_data {};
385template<typename T> struct Direction : Dir_in {};
386template<typename T> struct Direction<T const &> : Dir_in {};
387template<typename T> struct Direction<T const *> : Dir_in {};
388template<typename T> struct Direction<T &> : Dir_out {};
389template<typename T> struct Direction<T *> : Dir_out {};
390
391template<typename T> struct _Clnt_noops :
392 Clnt_noops<typename Detail::_Plain<typename _Elem<T>::arg_type>::type>
393{};
394
395namespace Detail {
396
397template<typename T, typename DIR, typename CLASS>
398struct _Clnt_val_ops :
399 Clnt_val_ops<typename Detail::_Plain<T>::type, DIR, CLASS> {};
400
401template<typename T,
402 typename ELEM = _Elem<T>,
403 typename CLNT_OPS = _Clnt_val_ops<typename ELEM::arg_type,
404 typename Direction<T>::type,
405 typename Class<typename Detail::_Plain<T>::type>::type>
406 >
407struct _Clnt_xmit : CLNT_OPS {};
408
409template<typename T,
410 typename ELEM = _Elem<T>,
411 typename SVR_OPS = Svr_val_ops<typename ELEM::svr_type,
412 typename Direction<T>::type,
413 typename Class<typename Detail::_Plain<T>::type>::type>
414 >
415struct _Svr_xmit : SVR_OPS {};
416
417} //namespace Detail
418
419// Specialize to alias a type X to T in client call signature.
420// Needs to be combined with a matching Elem< X > : Elem< T > specialization.
421// Or alternatively X needs to inherit from T.
422template<typename T> struct Clnt_xmit : Detail::_Clnt_xmit<T> {};
423// Specialize to alias a type X to T in server op_... signature.
424// Needs to be combined with a matching Elem< X > : Elem< T > specialization.
425// Or alternatively X needs to inherit from T.
426template<typename T> struct Svr_xmit : Detail::_Svr_xmit<T> {};
427
428}}} // namespace Msg, Ipc, L4
429
430
Error codes.
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:58
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:57
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:295
UTCB definitions.
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: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
IPC related functionality.
Definition ipc_array:13
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:361
Defines server-side handling for MTYPE server arguments.
Definition ipc_basics:281
True meta value.
Definition types:324