L4Re - L4 Runtime Environment
error_helper
Go to the documentation of this file.
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 
32 namespace L4Re {
33 
34 #ifdef __EXCEPTIONS
35 namespace Priv {
36 inline long __attribute__((__noreturn__)) __runtime_error(long err, char const *extra);
37 
38 inline long __runtime_error(long err, char const *extra)
39 {
40  switch (err)
41  {
42  case -L4_ENOENT: throw (L4::Element_not_found(extra));
43  case -L4_ENOMEM: throw (L4::Out_of_memory(extra));
44  case -L4_EEXIST: throw (L4::Element_already_exists(extra));
45  case -L4_ERANGE: throw (L4::Bounds_error(extra));
46  default: throw (L4::Runtime_error(err, extra));
47  }
48 }
49 
50 }
51 
52 /**
53  * \brief Generate C++ exception on error
54  *
55  * \param err Error value, if negative exception will be thrown
56  * \param extra Optional text for exception (default "")
57  * \param ret Optional value for exception, default is error value (err)
58  *
59  * This function throws an exception if the err is negative and
60  * otherwise returns err.
61  */
62 inline
63 long chksys(long err, char const *extra = "", long ret = 0)
64 {
65  if (L4_UNLIKELY(err < 0))
66  Priv::__runtime_error(ret ? ret : err, extra);
67 
68  return err;
69 }
70 
71 /**
72  * \brief Generate C++ exception on error
73  *
74  * \param t Message tag.
75  * \param extra Optional text for exception (default "")
76  * \param utcb Option UTCB
77  * \param ret Optional value for exception, default is error value (err)
78  *
79  * This function throws an exception if the message tag contains an error or
80  * the label in the message tag is negative. Otherwise the label in the
81  * message tag is returned.
82  */
83 inline
84 long chksys(l4_msgtag_t const &t, char const *extra = "",
85  l4_utcb_t *utcb = l4_utcb(), long ret = 0)
86 {
87  if (L4_UNLIKELY(t.has_error()))
88  Priv::__runtime_error(ret ? ret : l4_error_u(t, utcb), extra);
89  else if (L4_UNLIKELY(t.label() < 0))
90  throw L4::Runtime_error(ret ? ret: t.label(), extra);
91 
92  return t.label();
93 }
94 
95 /**
96  * \brief Generate C++ exception on error
97  *
98  * \param t Message tag.
99  * \param utcb UTCB.
100  * \param extra Optional text for exception (default "")
101  *
102  * This function throws an exception if the message tag contains an error or
103  * the label in the message tag is negative. Otherwise the label in the
104  * message tag is returned.
105  */
106 inline
107 long chksys(l4_msgtag_t const &t, l4_utcb_t *utcb, char const *extra = "")
108 { return chksys(t, extra, utcb); }
109 
110 #if 0
111 inline
112 long chksys(long ret, long err, char const *extra = "")
113 {
114  if (L4_UNLIKELY(ret < 0))
115  Priv::__runtime_error(err, extra);
116 
117  return ret;
118 }
119 #endif
120 
121 /**
122  * Check for valid capability or raise C++ exception
123  *
124  * \tparam T Type of object to check, must be capability-like
125  * (L4::Cap, L4Re::Util::Unique_cap etc.)
126  *
127  * \param cap Capability value to check.
128  * \param extra Optional text for exception.
129  * \param err Error value for exception or 0 if the capability value
130  * should be used.
131  *
132  * This function checks whether the capability is valid. If the capability
133  * is invalid an C++ exception is generated, using err if err is not zero,
134  * otherwise the capability value is used. A valid capability will just be
135  * returned.
136  */
137 template<typename T>
138 inline
139 #if __cplusplus >= 201103L
140 T chkcap(T &&cap, char const *extra = "", long err = -L4_ENOMEM)
141 #else
142 T chkcap(T cap, char const *extra = "", long err = -L4_ENOMEM)
143 #endif
144 {
145  if (L4_UNLIKELY(!cap.is_valid()))
146  Priv::__runtime_error(err ? err : cap.cap(), extra);
147 
148 #if __cplusplus >= 201103L
149  return cxx::forward<T>(cap);
150 #else
151  return cap;
152 #endif
153 }
154 
155 /**
156  * Test a message tag for IPC errors.
157  *
158  * \param tag Message tag returned by the IPC.
159  * \param extra Exception message in case of error.
160  * \param utcb The UTCB used in the IPC operation.
161  *
162  * \returns On IPC error an exception is thrown, otherwise `tag` is returned.
163  * \throws L4::Runtime_exception with the translated IPC error code
164  *
165  * This function does not check the message tag's label value.
166  *
167  * \note This must be called on a message tag before the UTCB is changed.
168  */
169 inline
170 l4_msgtag_t
171 chkipc(l4_msgtag_t tag, char const *extra = "",
172  l4_utcb_t *utcb = l4_utcb())
173 {
174  if (L4_UNLIKELY(tag.has_error()))
175  chksys(l4_error_u(tag, utcb), extra);
176 
177  return tag;
178 }
179 #endif
180 
181 }