Loading...
Searching...
No Matches
ipc_basics
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include "types"
#include <l4/sys/utcb.h>
#include <l4/sys/err.h>
namespace L4 {
namespace Ipc {
namespace Msg {
using L4::Types::True;
using L4::Types::False;
constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
{ return (bytes + align - 1) & ~(align - 1); }
template<typename T>
constexpr unsigned long align_to(unsigned long bytes) noexcept
{ return align_to(bytes, __alignof(T)); }
template<typename T>
constexpr bool check_size(unsigned offset, unsigned limit) noexcept
{
return offset + sizeof(T) <= limit;
}
template<typename T, typename CTYPE>
inline bool check_size(unsigned offset, unsigned limit, CTYPE cnt) noexcept
{
if (L4_UNLIKELY(sizeof(CTYPE) <= sizeof(unsigned) &&
~0U / sizeof(T) <= static_cast<unsigned>(cnt)))
return false;
if (L4_UNLIKELY(sizeof(CTYPE) > sizeof(unsigned) &&
static_cast<CTYPE>(~0U / sizeof(T)) <= cnt))
return false;
return sizeof(T) * cnt <= limit - offset;
}
enum
{
Word_bytes = sizeof(l4_umword_t),
Item_words = 2,
Item_bytes = Word_bytes * Item_words,
Mr_words = L4_UTCB_GENERIC_DATA_SIZE,
Mr_bytes = Word_bytes * Mr_words,
Br_bytes = Word_bytes * L4_UTCB_GENERIC_BUFFERS_SIZE,
};
template<typename T>
inline int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
{
offs = align_to<T>(offs);
if (L4_UNLIKELY(!check_size<T>(offs, limit)))
return -L4_EMSGTOOLONG;
*reinterpret_cast<typename L4::Types::Remove_const<T>::type *>(msg + offs) = v;
return offs + sizeof(T);
}
template<typename T>
inline int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
{
offs = align_to<T>(offs);
if (L4_UNLIKELY(!check_size<T>(offs, limit)))
return -L4_EMSGTOOSHORT;
v = *reinterpret_cast<T *>(msg + offs);
return offs + sizeof(T);
}
struct Dir_in { typedef Dir_in type; typedef Dir_in dir; };
struct Dir_out { typedef Dir_out type; typedef Dir_out dir; };
struct Cls_data { typedef Cls_data type; typedef Cls_data cls; };
struct Cls_item { typedef Cls_item type; typedef Cls_item cls; };
struct Cls_buffer { typedef Cls_buffer type; typedef Cls_buffer cls; };
// Typical combinations
struct Do_in_data : Dir_in, Cls_data {};
struct Do_out_data : Dir_out, Cls_data {};
struct Do_in_items : Dir_in, Cls_item {};
struct Do_out_items : Dir_out, Cls_item {};
struct Do_rcv_buffers : Dir_in, Cls_buffer {};
// implementation details
namespace Detail {
template<typename T> struct _Plain
{
typedef T type;
static T deref(T v) noexcept { return v; }
};
template<typename T> struct _Plain<T *>
{
typedef T type;
static T &deref(T *v) noexcept { return *v; }
};
template<typename T> struct _Plain<T &>
{
typedef T type;
static T &deref(T &v) noexcept { return v; }
};
template<typename T> struct _Plain<T const &>
{
typedef T type;
static T const &deref(T const &v) noexcept { return v; }
};
template<typename T> struct _Plain<T const *>
{
typedef T type;
static T const &deref(T const *v) noexcept { return *v; }
};
}
template<typename MTYPE, typename DIR, typename CLASS> struct Clnt_val_ops;
template<typename T> struct Clnt_noops
{
template<typename A, typename B>
static constexpr int to_msg(char *, unsigned offset, unsigned, T, A, B) noexcept
{ return offset; }
template<typename A, typename B>
static constexpr int from_msg(char *, unsigned offset, unsigned, long, T const &, A, B) noexcept
{ return offset; }
};
template<typename T> struct Svr_noops
{
template<typename A, typename B>
static constexpr int from_svr(char *, unsigned offset, unsigned, long, T, A, B) noexcept
{ return offset; }
template<typename A, typename B>
static constexpr int to_svr(char *, unsigned offset, unsigned, T, A, B) noexcept
{ return offset; }
};
template<typename MTYPE, typename CLASS>
struct Clnt_val_ops<MTYPE, Dir_in, CLASS> : Clnt_noops<MTYPE>
{
using Clnt_noops<MTYPE>::to_msg;
static int to_msg(char *msg, unsigned offset, unsigned limit,
MTYPE arg, Dir_in, CLASS) noexcept
{ return msg_add<MTYPE>(msg, offset, limit, arg); }
};
template<typename MTYPE, typename CLASS>
struct Clnt_val_ops<MTYPE, Dir_out, CLASS> : Clnt_noops<MTYPE>
{
using Clnt_noops<MTYPE>::from_msg;
static int from_msg(char *msg, unsigned offset, unsigned limit, long,
MTYPE &arg, Dir_out, CLASS) noexcept
{ return msg_get<MTYPE>(msg, offset, limit, arg); }
};
template<typename MTYPE, typename DIR, typename CLASS> struct Svr_val_ops;
template<typename MTYPE, typename CLASS>
struct Svr_val_ops<MTYPE, Dir_in, CLASS> : Svr_noops<MTYPE>
{
using Svr_noops<MTYPE>::to_svr;
static int to_svr(char *msg, unsigned offset, unsigned limit,
MTYPE &arg, Dir_in, CLASS) noexcept
{ return msg_get<MTYPE>(msg, offset, limit, arg); }
};
template<typename MTYPE, typename CLASS>
struct Svr_val_ops<MTYPE, Dir_out, CLASS> : Svr_noops<MTYPE>
{
using Svr_noops<MTYPE>::to_svr;
static int to_svr(char *, unsigned offs, unsigned limit,
MTYPE &, Dir_out, CLASS) noexcept
{
offs = align_to<MTYPE>(offs);
if (L4_UNLIKELY(!check_size<MTYPE>(offs, limit)))
return -L4_EMSGTOOLONG;
return offs + sizeof(MTYPE);
}
using Svr_noops<MTYPE>::from_svr;
static int from_svr(char *msg, unsigned offset, unsigned limit, long,
MTYPE arg, Dir_out, CLASS) noexcept
{ return msg_add<MTYPE>(msg, offset, limit, arg); }
};
template<typename T> struct Elem
{
typedef T arg_type;
typedef T svr_type;
typedef T svr_arg_type; // might by const & (depending on the size)
enum { Is_optional = false };
};
template<typename T> struct Elem<T &>
{
typedef T &arg_type;
typedef T svr_type;
typedef T &svr_arg_type;
enum { Is_optional = false };
};
template<typename T> struct Elem<T const &>
{
typedef T const &arg_type;
typedef T svr_type;
// as the RPC uses a const reference we use it here too,
// we could also use pass by value depending on the size
typedef T const &svr_arg_type;
enum { Is_optional = false };
};
template<typename T> struct Elem<T *> : Elem<T &>
{
typedef T *arg_type;
};
template<typename T> struct Elem<T const *> : Elem<T const &>
{
typedef T const *arg_type;
};
template<typename T> struct Is_valid_rpc_type : L4::Types::True {};
// Static assertions outside functions work only properly from C++11
// onewards. On earlier version make sure the compiler fails on an ugly
// undefined struct instead.
template<typename T, bool B> struct Error_invalid_rpc_parameter_used;
template<typename T> struct Error_invalid_rpc_parameter_used<T, true> {};
#if __cplusplus >= 201103L
template<typename T>
struct _Elem : Elem<T>
{
static_assert(Is_valid_rpc_type<T>::value,
"L4::Ipc::Msg::_Elem<T>: type T is not a valid RPC parameter type.");
};
#else
template<typename T>
struct _Elem : Elem<T>,
Error_invalid_rpc_parameter_used<T, Is_valid_rpc_type<T>::value>
{};
#endif
template<typename T> struct Class : Cls_data {};
template<typename T> struct Direction : Dir_in {};
template<typename T> struct Direction<T const &> : Dir_in {};
template<typename T> struct Direction<T const *> : Dir_in {};
template<typename T> struct Direction<T &> : Dir_out {};
template<typename T> struct Direction<T *> : Dir_out {};
template<typename T> struct _Clnt_noops :
Clnt_noops<typename Detail::_Plain<typename _Elem<T>::arg_type>::type>
{};
namespace Detail {
template<typename T, typename DIR, typename CLASS>
struct _Clnt_val_ops :
Clnt_val_ops<typename Detail::_Plain<T>::type, DIR, CLASS> {};
template<typename T,
typename ELEM = _Elem<T>,
typename CLNT_OPS = _Clnt_val_ops<typename ELEM::arg_type,
typename Direction<T>::type,
typename Class<typename Detail::_Plain<T>::type>::type>
>
struct _Clnt_xmit : CLNT_OPS {};
template<typename T,
typename ELEM = _Elem<T>,
typename SVR_OPS = Svr_val_ops<typename ELEM::svr_type,
typename Direction<T>::type,
typename Class<typename Detail::_Plain<T>::type>::type>
>
struct _Svr_xmit : SVR_OPS {};
} //namespace Detail
template<typename T> struct Clnt_xmit : Detail::_Clnt_xmit<T> {};
template<typename T> struct Svr_xmit : Detail::_Svr_xmit<T> {};
}}} // namespace Msg, Ipc, L4
err.h
Error codes.
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
L4_EMSGTOOLONG
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:57
L4_EMSGTOOSHORT
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:56
L4_UNLIKELY
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:284
utcb.h
UTCB definitions.
L4::Ipc::Msg
IPC Message related functionality.
Definition ipc_array:154
L4::Ipc::Msg::check_size
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
L4::Ipc::Msg::align_to
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
L4::Ipc::Msg::Br_bytes
@ Br_bytes
number of bytes available in the UTCB buffer registers
Definition ipc_basics:98
L4::Ipc::Msg::Item_words
@ Item_words
number of message words for one message item
Definition ipc_basics:90
L4::Ipc::Msg::Mr_bytes
@ Mr_bytes
number of bytes available in the UTCB message registers
Definition ipc_basics:96
L4::Ipc::Msg::Item_bytes
@ Item_bytes
number of bytes for one message item
Definition ipc_basics:92
L4::Ipc::Msg::Word_bytes
@ Word_bytes
number of bytes for one message word
Definition ipc_basics:88
L4::Ipc::Msg::Mr_words
@ Mr_words
number of message words available in the UTCB
Definition ipc_basics:94
L4::Ipc::Msg::msg_add
int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
Add some data to a message at offs.
Definition ipc_basics:114
L4::Ipc::Msg::msg_get
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::Ipc
IPC related functionality.
Definition ipc_array:13
L4
L4 low-level kernel interface.
Definition l4sys-l4f-groups.dox:50
L4::Ipc::Msg::Cls_buffer
Marker type for receive buffer values.
Definition ipc_basics:154
L4::Ipc::Msg::Cls_data
Marker type for data values.
Definition ipc_basics:150
L4::Ipc::Msg::Cls_item
Marker type for item values.
Definition ipc_basics:152
L4::Ipc::Msg::Dir_in
Marker type for input values.
Definition ipc_basics:145
L4::Ipc::Msg::Dir_out
Marker type for output values.
Definition ipc_basics:147
L4::Ipc::Msg::Do_in_data
Marker for Input data.
Definition ipc_basics:158
L4::Ipc::Msg::Do_in_items
Marker for Input items.
Definition ipc_basics:162
L4::Ipc::Msg::Do_out_data
Marker for Output data.
Definition ipc_basics:160
L4::Ipc::Msg::Do_out_items
Marker for Output items.
Definition ipc_basics:164
L4::Ipc::Msg::Do_rcv_buffers
Marker for receive buffers.
Definition ipc_basics:166
L4::Ipc::Msg::Is_valid_rpc_type
Type trait defining a valid RPC parameter type.
Definition ipc_basics:339
L4::Ipc::Msg::Svr_val_ops
Defines client-side handling of `MTYPE' as RPC argument.
Definition ipc_basics:264
L4::Types::True
True meta value.
Definition types:300
types