Loading...
Searching...
No Matches
ipc_array
// 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 "ipc_basics"
#include "ipc_types"
namespace L4 { namespace Ipc L4_EXPORT {
typedef unsigned short Array_len_default;
template< typename ELEM_TYPE, typename LEN_TYPE = Array_len_default >
struct Array_ref
{
typedef ELEM_TYPE *ptr_type;
typedef LEN_TYPE len_type;
len_type length;
ptr_type data;
Array_ref() = default;
Array_ref(len_type length, ptr_type data)
: length(length), data(data)
{}
template<typename X> struct Non_const
{ typedef Array_ref<X, LEN_TYPE> type; };
template<typename X> struct Non_const<X const>
{ typedef Array_ref<X, LEN_TYPE> type; };
Array_ref(typename Non_const<ELEM_TYPE>::type const &other)
: length(other.length), data(other.data)
{}
Array_ref &operator = (typename Non_const<ELEM_TYPE>::type const &other)
{
this->length = other.length;
this->data = other.data;
return *this;
}
};
template<typename ELEM_TYPE, typename LEN_TYPE = Array_len_default>
struct Array : Array_ref<ELEM_TYPE , LEN_TYPE>
{
Array() {}
Array(LEN_TYPE length, ELEM_TYPE *data)
: Array_ref<ELEM_TYPE, LEN_TYPE>(length, data)
{}
template<typename X> struct Non_const
{ typedef Array<X, LEN_TYPE> type; };
template<typename X> struct Non_const<X const>
{ typedef Array<X, LEN_TYPE> type; };
Array(typename Non_const<ELEM_TYPE>::type const &other)
: Array_ref<ELEM_TYPE, LEN_TYPE>(other.length, other.data)
{}
Array &operator = (typename Non_const<ELEM_TYPE>::type const &other)
{
this->length = other.length;
this->data = other.data;
return *this;
}
};
template< typename ELEM_TYPE,
typename LEN_TYPE = Array_len_default,
LEN_TYPE MAX = (L4_UTCB_GENERIC_DATA_SIZE *
sizeof(l4_umword_t)) / sizeof(ELEM_TYPE) >
struct Array_in_buf
{
typedef Array_ref<ELEM_TYPE, LEN_TYPE> array;
typedef Array_ref<ELEM_TYPE const, LEN_TYPE> const_array;
ELEM_TYPE data[MAX];
LEN_TYPE length;
void copy_in(const_array a)
{
length = a.length;
if (length > MAX)
length = MAX;
for (LEN_TYPE i = 0; i < length; ++i)
data[i] = a.data[i];
}
Array_in_buf(const_array a) { copy_in(a); }
Array_in_buf(array a) { copy_in(a); }
};
// implementation details for transmission
namespace Msg {
template<typename A, typename LEN>
struct Elem< Array<A, LEN> >
{
typedef Array<A, LEN> arg_type;
typedef Array_ref<A, LEN> svr_type;
typedef svr_type svr_arg_type;
enum { Is_optional = false };
};
template<typename A, typename LEN>
struct Elem< Array<A, LEN> & >
{
typedef Array<A, LEN> &arg_type;
typedef Array_ref<A, LEN> svr_type;
typedef svr_type &svr_arg_type;
enum { Is_optional = false };
};
template<typename A, typename LEN>
struct Elem< Array_ref<A, LEN> & >
{
typedef Array_ref<A, LEN> &arg_type;
typedef Array_ref<typename L4::Types::Remove_const<A>::type, LEN> svr_type;
typedef svr_type &svr_arg_type;
enum { Is_optional = false };
};
template<typename A> struct Class<Array<A> > : Class<A>::type {};
template<typename A> struct Class<Array_ref<A> > : Class<A>::type {};
namespace Detail {
template<typename A, typename LEN, typename ARRAY, bool REF>
struct Clnt_val_ops_d_in : Clnt_noops<ARRAY>
{
using Clnt_noops<ARRAY>::to_msg;
static int to_msg(char *msg, unsigned offset, unsigned limit,
ARRAY a, Dir_in, Cls_data)
{
offset = align_to<LEN>(offset);
if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
return -L4_EMSGTOOLONG;
*reinterpret_cast<LEN *>(msg + offset) = a.length;
offset = align_to<A>(offset + sizeof(LEN));
if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
return -L4_EMSGTOOLONG;
typedef typename L4::Types::Remove_const<A>::type elem_type;
elem_type *data = reinterpret_cast<elem_type*>(msg + offset);
// we do not correctly handle overlaps
if (!REF || data != a.data)
{
for (LEN i = 0; i < a.length; ++i)
data[i] = a.data[i];
}
return offset + a.length * sizeof(A);
}
};
} // namespace Detail
template<typename A, typename LEN>
struct Clnt_val_ops<Array<A, LEN>, Dir_in, Cls_data> :
Detail::Clnt_val_ops_d_in<A, LEN, Array<A, LEN>, false> {};
template<typename A, typename LEN>
struct Clnt_val_ops<Array_ref<A, LEN>, Dir_in, Cls_data> :
Detail::Clnt_val_ops_d_in<A, LEN, Array_ref<A, LEN>, true> {};
template<typename A, typename LEN, typename CLASS>
struct Svr_val_ops< Array_ref<A, LEN>, Dir_in, CLASS >
: Svr_noops< Array_ref<A, LEN> >
{
typedef Array_ref<A, LEN> svr_type;
using Svr_noops<svr_type>::to_svr;
static int to_svr(char *msg, unsigned offset, unsigned limit,
svr_type &a, Dir_in, Cls_data)
{
offset = align_to<LEN>(offset);
if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
return -L4_EMSGTOOSHORT;
a.length = *reinterpret_cast<LEN *>(msg + offset);
offset = align_to<A>(offset + sizeof(LEN));
if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
return -L4_EMSGTOOSHORT;
a.data = reinterpret_cast<A*>(msg + offset);
return offset + a.length * sizeof(A);
}
};
template<typename A, typename LEN>
struct Svr_xmit< Array<A, LEN> > : Svr_xmit< Array_ref<A, LEN> > {};
template<typename A, typename LEN>
struct Clnt_val_ops<Array<A, LEN>, Dir_out, Cls_data> : Clnt_noops<Array<A, LEN> >
{
typedef Array<A, LEN> type;
using Clnt_noops<type>::from_msg;
static int from_msg(char *msg, unsigned offset, unsigned limit, long,
type &a, Dir_out, Cls_data)
{
offset = align_to<LEN>(offset);
if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
return -L4_EMSGTOOSHORT;
LEN l = *reinterpret_cast<LEN *>(msg + offset);
offset = align_to<A>(offset + sizeof(LEN));
if (L4_UNLIKELY(!check_size<A>(offset, limit, l)))
return -L4_EMSGTOOSHORT;
A *data = reinterpret_cast<A*>(msg + offset);
if (l > a.length)
l = a.length;
else
a.length = l;
for (unsigned i = 0; i < l; ++i)
a.data[i] = data[i];
return offset + l * sizeof(A);
};
};
template<typename A, typename LEN>
struct Clnt_val_ops<Array_ref<A, LEN>, Dir_out, Cls_data> :
Clnt_noops<Array_ref<A, LEN> >
{
typedef Array_ref<A, LEN> type;
using Clnt_noops<type>::from_msg;
static int from_msg(char *msg, unsigned offset, unsigned limit, long,
type &a, Dir_out, Cls_data)
{
offset = align_to<LEN>(offset);
if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
return -L4_EMSGTOOSHORT;
LEN l = *reinterpret_cast<LEN *>(msg + offset);
offset = align_to<A>(offset + sizeof(LEN));
if (L4_UNLIKELY(!check_size<A>(offset, limit, l)))
return -L4_EMSGTOOSHORT;
a.data = reinterpret_cast<A*>(msg + offset);
a.length = l;
return offset + l * sizeof(A);
};
};
template<typename A, typename LEN, typename CLASS>
struct Svr_val_ops<Array_ref<A, LEN>, Dir_out, CLASS> :
Svr_noops<Array_ref<typename L4::Types::Remove_const<A>::type, LEN> &>
{
typedef typename L4::Types::Remove_const<A>::type elem_type;
typedef Array_ref<elem_type, LEN> &svr_type;
using Svr_noops<svr_type>::to_svr;
static int to_svr(char *msg, unsigned offset, unsigned limit,
svr_type a, Dir_out, Cls_data)
{
offset = align_to<LEN>(offset);
if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
return -L4_EMSGTOOLONG;
offset = align_to<A>(offset + sizeof(LEN));
a.data = reinterpret_cast<elem_type *>(msg + offset);
a.length = (limit-offset) / sizeof(A);
return offset;
}
using Svr_noops<svr_type>::from_svr;
static int from_svr(char *msg, unsigned offset, unsigned limit, long,
svr_type a, Dir_out, Cls_data)
{
offset = align_to<LEN>(offset);
if (L4_UNLIKELY(!check_size<LEN>(offset, limit)))
return -L4_EMSGTOOLONG;
*reinterpret_cast<LEN *>(msg + offset) = a.length;
offset = align_to<A>(offset + sizeof(LEN));
if (L4_UNLIKELY(!check_size<A>(offset, limit, a.length)))
return -L4_EMSGTOOLONG;
return offset + a.length * sizeof(A);
}
};
template<typename A, typename LEN>
struct Svr_xmit<Array<A, LEN> &> : Svr_xmit<Array_ref<A, LEN> &> {};
// Pointer to array is not implemented.
template<typename A, typename LEN>
struct Is_valid_rpc_type< Array_ref<A, LEN> *> : L4::Types::False {};
// Optional input arrays are not implemented.
template<typename A, typename LEN>
struct Is_valid_rpc_type< Opt<Array_ref<A, LEN> > > : L4::Types::False {};
} // namespace Msg
}}
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
L4_EXPORT
#define L4_EXPORT
Attribute to mark functions, variables, and data types as being exported from a library.
Definition compiler.h:214
ipc_types
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
IPC related functionality.
Definition ipc_array:13
L4::Ipc::Array_len_default
unsigned short Array_len_default
Default type for passing length of an array.
Definition ipc_array:16
L4
L4 low-level kernel interface.
Definition l4sys-l4f-groups.dox:50
L4::Ipc::Array_in_buf< CHAR, LEN_TYPE, MAX >::length
LEN_TYPE length
Definition ipc_array:134
L4::Ipc::Array_in_buf::copy_in
void copy_in(const_array a)
copy in data from a source array
Definition ipc_array:137
L4::Ipc::Array_in_buf::Array_in_buf
Array_in_buf(array a)
Make Array_in_buf from a non-const array.
Definition ipc_array:150
L4::Ipc::Array_in_buf< CHAR, LEN_TYPE, MAX >::data
CHAR data[MAX]
Definition ipc_array:132
L4::Ipc::Array_in_buf::Array_in_buf
Array_in_buf(const_array a)
Make Array_in_buf from a const array.
Definition ipc_array:148
L4::Ipc::Array_ref
Array reference data type for arrays located in the message.
Definition ipc_array:29
L4::Ipc::Array
Array data type for dynamically sized arrays in RPCs.
Definition ipc_array:82
L4::Ipc::Array::Array
Array()
Make array.
Definition ipc_array:84
L4::Ipc::Array::Array
Array(LEN_TYPE length, ELEM_TYPE *data)
Make array from length and data pointer.
Definition ipc_array:86
L4::Ipc::Array::Array
Array(typename Non_const< ELEM_TYPE >::type const &other)
Make a const array from a non-const array.
Definition ipc_array:97
L4::Ipc::Msg::Cls_data
Marker type for data values.
Definition ipc_basics:150
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::Elem< Array< A, LEN > >::svr_type
Array_ref< A, LEN > svr_type
Array_ref<> at the server side.
Definition ipc_array:163
L4::Ipc::Msg::Elem< Array< A, LEN > >::arg_type
Array< A, LEN > arg_type
Array<> as argument at the interface.
Definition ipc_array:161
L4::Ipc::Msg::Elem< Array< A, LEN > & >::svr_type
Array_ref< A, LEN > svr_type
Array_ref<> as server storage type.
Definition ipc_array:175
L4::Ipc::Msg::Elem< Array< A, LEN > & >::svr_arg_type
svr_type & svr_arg_type
Array_ref<> & at the server side.
Definition ipc_array:177
L4::Ipc::Msg::Elem< Array< A, LEN > & >::arg_type
Array< A, LEN > & arg_type
Array<> & at the interface.
Definition ipc_array:173
L4::Ipc::Msg::Elem< Array_ref< A, LEN > & >::svr_type
Array_ref< typename L4::Types::Remove_const< A >::type, LEN > svr_type
Array_ref<> as server storage.
Definition ipc_array:188
L4::Ipc::Msg::Elem< Array_ref< A, LEN > & >::svr_arg_type
svr_type & svr_arg_type
Array_ref<> & as server argument.
Definition ipc_array:190
L4::Ipc::Msg::Elem< Array_ref< A, LEN > & >::arg_type
Array_ref< A, LEN > & arg_type
Array_ref<> at the interface.
Definition ipc_array:186
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
types