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 "ipc_basics" 22 23namespace L4 { namespace Ipc L4_EXPORT { 24 25// --------------------------------------------------------------- 26/** 27 * Dynamically sized output array of type T. 28 * \tparam T The data-type of each array element. 29 * 30 * Ret_array<> is a special dynamically sized output array 31 * where the number of transmitted elements is passed in 32 * the return value of the call (if positive) 33 */ 34template<typename T> struct L4_EXPORT Ret_array 35{ 36 typedef T const **ptr_type; 37 38 T *value; 39 unsigned max; 40 Ret_array() {} 41 Ret_array(T *v, unsigned max) : value(v), max(max) {} 42}; 43 44namespace Msg { 45 46template<typename A> struct Elem< Ret_array<A> > 47{ 48 enum { Is_optional = false }; 49 typedef Ret_array<A> type; 50 typedef typename type::ptr_type arg_type; 51 typedef type svr_type; 52 typedef type svr_arg_type; 53}; 54 55template<typename A> 56struct Is_valid_rpc_type<Ret_array<A> *> : L4::Types::False {}; 57template<typename A> 58struct Is_valid_rpc_type<Ret_array<A> &> : L4::Types::False {}; 59template<typename A> 60struct Is_valid_rpc_type<Ret_array<A> const &> : L4::Types::False {}; 61template<typename A> 62struct Is_valid_rpc_type<Ret_array<A> const *> : L4::Types::False {}; 63 64template<typename A> struct Class< Ret_array<A> > : Class<A>::type {}; 65template<typename A> struct Direction< Ret_array<A> > : Dir_out {}; 66 67template<typename A, typename CLASS> 68struct Clnt_val_ops<A const *, Dir_out, CLASS> : Clnt_noops<A const *> 69{ 70 using Clnt_noops<A const *>::from_msg; 71 static int from_msg(char *msg, unsigned offset, unsigned limit, long ret, 72 A const *&arg, Dir_out, Cls_data) 73 { 74 offset = align_to<A>(offset); 75 arg = reinterpret_cast<A const *>(msg + offset); 76 if (L4_UNLIKELY(!check_size<A>(offset, limit, ret))) 77 return -1; 78 79 return offset + ret * sizeof(A); 80 } 81}; 82 83template<typename A, typename CLASS> 84struct Svr_val_ops<Ret_array<A>, Dir_out, CLASS> : 85 Svr_noops<Ret_array<A> > 86{ 87 typedef Ret_array<A> ret_array; 88 using Svr_noops<ret_array>::from_svr; 89 static int from_svr(char *, unsigned offset, unsigned limit, long ret, 90 ret_array const &, Dir_out, CLASS) 91 { 92 offset = align_to<A>(offset); 93 if (L4_UNLIKELY(!check_size<A>(offset, limit, ret))) 94 return -1; 95 offset += sizeof(A) * ret; 96 return offset; 97 } 98 99 using Svr_noops<ret_array>::to_svr; 100 static int to_svr(char *msg, unsigned offset, unsigned limit, 101 ret_array &arg, Dir_out, CLASS) 102 { 103 // there can be actually no limit check here, as this 104 // is variably sized output array 105 // FIXME: we could somehow makesure that this is the last 106 // output value... 107 offset = align_to<A>(offset); 108 arg = ret_array(reinterpret_cast<A*>(msg + offset), 109 (limit - offset) / sizeof(A)); 110 // FIXME: we dont know the length of the array here so, cheat 111 return offset; 112 } 113}; 114} // namespace Msg 115 116}} 117