1// vi:set ft=cpp: -*- Mode: C++ -*- 2/** 3 * \file 4 * \brief Error helper. 5 */ 6/* 7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, 8 * Alexander Warg <warg@os.inf.tu-dresden.de>, 9 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de> 10 * economic rights: Technische Universität Dresden (Germany) 11 * 12 * This file is part of TUD:OS and distributed under the terms of the 13 * GNU General Public License 2. 14 * Please see the COPYING-GPL-2 file for details. 15 * 16 * As a special exception, you may use this file as part of a free software 17 * library without restriction. Specifically, if other files instantiate 18 * templates or use macros or inline functions from this file, or you compile 19 * this file and link it with other files to produce an executable, this 20 * file does not by itself cause the resulting executable to be covered by 21 * the GNU General Public License. This exception does not however 22 * invalidate any other reasons why the executable file might be covered by 23 * the GNU General Public License. 24 */ 25#pragma once 26 27#include <l4/sys/types.h> 28#include <l4/cxx/exceptions> 29#include <l4/cxx/type_traits> 30#include <l4/sys/err.h> 31 32namespace L4Re { 33 34#ifdef __EXCEPTIONS 35 36/** 37 * \brief Generate C++ exception 38 * 39 * \param err Error value 40 * \param extra Optional text for exception (default "") 41 * 42 * This function throws an L4 exception. The exact exception type depends on 43 * the error value (err). This function does never return. 44 */ 45[[noreturn]] inline void throw_error(long err, char const *extra = "") 46{ 47 switch (err) 48 { 49 case -L4_ENOENT: throw (L4::Element_not_found(extra)); 50 case -L4_ENOMEM: throw (L4::Out_of_memory(extra)); 51 case -L4_EEXIST: throw (L4::Element_already_exists(extra)); 52 case -L4_ERANGE: throw (L4::Bounds_error(extra)); 53 default: throw (L4::Runtime_error(err, extra)); 54 } 55} 56 57/** 58 * \brief Generate C++ exception on error 59 * 60 * \param err Error value, if negative exception will be thrown 61 * \param extra Optional text for exception (default "") 62 * \param ret Optional value for exception, default is error value (err) 63 * 64 * This function throws an exception if the err is negative and 65 * otherwise returns err. 66 */ 67inline 68long chksys(long err, char const *extra = "", long ret = 0) 69{ 70 if (L4_UNLIKELY(err < 0)) 71 throw_error(ret ? ret : err, extra); 72 73 return err; 74} 75 76/** 77 * \brief Generate C++ exception on error 78 * 79 * \param t Message tag. 80 * \param extra Optional text for exception (default "") 81 * \param utcb Option UTCB 82 * \param ret Optional value for exception, default is error value (err) 83 * 84 * This function throws an exception if the message tag contains an error or 85 * the label in the message tag is negative. Otherwise the label in the 86 * message tag is returned. 87 */ 88inline 89long chksys(l4_msgtag_t const &t, char const *extra = "", 90 l4_utcb_t *utcb = l4_utcb(), long ret = 0) 91{ 92 if (L4_UNLIKELY(t.has_error())) 93 throw_error(ret ? ret : l4_error_u(t, utcb), extra); 94 else if (L4_UNLIKELY(t.label() < 0)) 95 throw_error(ret ? ret: t.label(), extra); 96 97 return t.label(); 98} 99 100/** 101 * \brief Generate C++ exception on error 102 * 103 * \param t Message tag. 104 * \param utcb UTCB. 105 * \param extra Optional text for exception (default "") 106 * 107 * This function throws an exception if the message tag contains an error or 108 * the label in the message tag is negative. Otherwise the label in the 109 * message tag is returned. 110 */ 111inline 112long chksys(l4_msgtag_t const &t, l4_utcb_t *utcb, char const *extra = "") 113{ return chksys(t, extra, utcb); } 114 115#if 0 116inline 117long chksys(long ret, long err, char const *extra = "") 118{ 119 if (L4_UNLIKELY(ret < 0)) 120 throw_error(err, extra); 121 122 return ret; 123} 124#endif 125 126/** 127 * Check for valid capability or raise C++ exception 128 * 129 * \tparam T Type of object to check, must be capability-like 130 * (L4::Cap, L4Re::Util::Unique_cap etc.) 131 * 132 * \param cap Capability value to check. 133 * \param extra Optional text for exception. 134 * \param err Error value for exception or 0 if the capability value 135 * should be used. 136 * 137 * This function checks whether the capability is valid. If the capability 138 * is invalid an C++ exception is generated, using err if err is not zero, 139 * otherwise the capability value is used. A valid capability will just be 140 * returned. 141 */ 142template<typename T> 143inline 144#if __cplusplus >= 201103L 145T chkcap(T &&cap, char const *extra = "", long err = -L4_ENOMEM) 146#else 147T chkcap(T cap, char const *extra = "", long err = -L4_ENOMEM) 148#endif 149{ 150 if (L4_UNLIKELY(!cap.is_valid())) 151 throw_error(err ? err : cap.cap(), extra); 152 153#if __cplusplus >= 201103L 154 return cxx::forward<T>(cap); 155#else 156 return cap; 157#endif 158} 159 160/** 161 * Test a message tag for IPC errors. 162 * 163 * \param tag Message tag returned by the IPC. 164 * \param extra Exception message in case of error. 165 * \param utcb The UTCB used in the IPC operation. 166 * 167 * \returns On IPC error an exception is thrown, otherwise `tag` is returned. 168 * \throws L4::Runtime_exception with the translated IPC error code 169 * 170 * This function does not check the message tag's label value. 171 * 172 * \note This must be called on a message tag before the UTCB is changed. 173 */ 174inline 175l4_msgtag_t 176chkipc(l4_msgtag_t tag, char const *extra = "", 177 l4_utcb_t *utcb = l4_utcb()) 178{ 179 if (L4_UNLIKELY(tag.has_error())) 180 chksys(l4_error_u(tag, utcb), extra); 181 182 return tag; 183} 184#endif 185 186} 187