1 use crate::{fmt, io::ErrorKind};
2
3 use super::abi;
4
5 /// Wraps a μITRON error code.
6 #[derive(Debug, Copy, Clone)]
7 pub struct ItronError {
8 er: abi::ER,
9 }
10
11 impl ItronError {
12 /// Construct `ItronError` from the specified error code. Returns `None` if the
13 /// error code does not represent a failure or warning.
14 #[inline]
new(er: abi::ER) -> Option<Self>15 pub fn new(er: abi::ER) -> Option<Self> {
16 if er < 0 { Some(Self { er }) } else { None }
17 }
18
19 /// Returns `Ok(er)` if `er` represents a success or `Err(_)` otherwise.
20 #[inline]
err_if_negative(er: abi::ER) -> Result<abi::ER, Self>21 pub fn err_if_negative(er: abi::ER) -> Result<abi::ER, Self> {
22 if let Some(error) = Self::new(er) { Err(error) } else { Ok(er) }
23 }
24
25 /// Get the raw error code.
26 #[inline]
as_raw(&self) -> abi::ER27 pub fn as_raw(&self) -> abi::ER {
28 self.er
29 }
30 }
31
32 impl fmt::Display for ItronError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 // Allow the platforms to extend `error_name`
35 if let Some(name) = crate::sys::error::error_name(self.er) {
36 write!(f, "{} ({})", name, self.er)
37 } else {
38 write!(f, "{}", self.er)
39 }
40 }
41 }
42
43 /// Describe the specified μITRON error code. Returns `None` if it's an
44 /// undefined error code.
error_name(er: abi::ER) -> Option<&'static str>45 pub fn error_name(er: abi::ER) -> Option<&'static str> {
46 match er {
47 // Success
48 er if er >= 0 => None,
49
50 // μITRON 4.0
51 abi::E_SYS => Some("system error"),
52 abi::E_NOSPT => Some("unsupported function"),
53 abi::E_RSFN => Some("reserved function code"),
54 abi::E_RSATR => Some("reserved attribute"),
55 abi::E_PAR => Some("parameter error"),
56 abi::E_ID => Some("invalid ID number"),
57 abi::E_CTX => Some("context error"),
58 abi::E_MACV => Some("memory access violation"),
59 abi::E_OACV => Some("object access violation"),
60 abi::E_ILUSE => Some("illegal service call use"),
61 abi::E_NOMEM => Some("insufficient memory"),
62 abi::E_NOID => Some("no ID number available"),
63 abi::E_OBJ => Some("object state error"),
64 abi::E_NOEXS => Some("non-existent object"),
65 abi::E_QOVR => Some("queue overflow"),
66 abi::E_RLWAI => Some("forced release from waiting"),
67 abi::E_TMOUT => Some("polling failure or timeout"),
68 abi::E_DLT => Some("waiting object deleted"),
69 abi::E_CLS => Some("waiting object state changed"),
70 abi::E_WBLK => Some("non-blocking code accepted"),
71 abi::E_BOVR => Some("buffer overflow"),
72
73 // The TOPPERS third generation kernels
74 abi::E_NORES => Some("insufficient system resources"),
75 abi::E_RASTER => Some("termination request raised"),
76 abi::E_COMM => Some("communication failure"),
77
78 _ => None,
79 }
80 }
81
decode_error_kind(er: abi::ER) -> ErrorKind82 pub fn decode_error_kind(er: abi::ER) -> ErrorKind {
83 match er {
84 // Success
85 er if er >= 0 => ErrorKind::Uncategorized,
86
87 // μITRON 4.0
88 // abi::E_SYS
89 abi::E_NOSPT => ErrorKind::Unsupported, // Some("unsupported function"),
90 abi::E_RSFN => ErrorKind::InvalidInput, // Some("reserved function code"),
91 abi::E_RSATR => ErrorKind::InvalidInput, // Some("reserved attribute"),
92 abi::E_PAR => ErrorKind::InvalidInput, // Some("parameter error"),
93 abi::E_ID => ErrorKind::NotFound, // Some("invalid ID number"),
94 // abi::E_CTX
95 abi::E_MACV => ErrorKind::PermissionDenied, // Some("memory access violation"),
96 abi::E_OACV => ErrorKind::PermissionDenied, // Some("object access violation"),
97 // abi::E_ILUSE
98 abi::E_NOMEM => ErrorKind::OutOfMemory, // Some("insufficient memory"),
99 abi::E_NOID => ErrorKind::OutOfMemory, // Some("no ID number available"),
100 // abi::E_OBJ
101 abi::E_NOEXS => ErrorKind::NotFound, // Some("non-existent object"),
102 // abi::E_QOVR
103 abi::E_RLWAI => ErrorKind::Interrupted, // Some("forced release from waiting"),
104 abi::E_TMOUT => ErrorKind::TimedOut, // Some("polling failure or timeout"),
105 // abi::E_DLT
106 // abi::E_CLS
107 // abi::E_WBLK
108 // abi::E_BOVR
109
110 // The TOPPERS third generation kernels
111 abi::E_NORES => ErrorKind::OutOfMemory, // Some("insufficient system resources"),
112 // abi::E_RASTER
113 // abi::E_COMM
114 _ => ErrorKind::Uncategorized,
115 }
116 }
117
118 /// Similar to `ItronError::err_if_negative(er).expect()` except that, while
119 /// panicking, it prints the message to `panic_output` and aborts the program
120 /// instead. This ensures the error message is not obscured by double
121 /// panicking.
122 ///
123 /// This is useful for diagnosing creation failures of synchronization
124 /// primitives that are used by `std`'s internal mechanisms. Such failures
125 /// are common when the system is mis-configured to provide a too-small pool for
126 /// kernel objects.
127 #[inline]
expect_success(er: abi::ER, msg: &&str) -> abi::ER128 pub fn expect_success(er: abi::ER, msg: &&str) -> abi::ER {
129 match ItronError::err_if_negative(er) {
130 Ok(x) => x,
131 Err(e) => fail(e, msg),
132 }
133 }
134
135 /// Similar to `ItronError::err_if_negative(er).expect()` but aborts instead.
136 ///
137 /// Use this where panicking is not allowed or the effect of the failure
138 /// would be persistent.
139 #[inline]
expect_success_aborting(er: abi::ER, msg: &&str) -> abi::ER140 pub fn expect_success_aborting(er: abi::ER, msg: &&str) -> abi::ER {
141 match ItronError::err_if_negative(er) {
142 Ok(x) => x,
143 Err(e) => fail_aborting(e, msg),
144 }
145 }
146
147 #[cold]
fail(e: impl fmt::Display, msg: &&str) -> !148 pub fn fail(e: impl fmt::Display, msg: &&str) -> ! {
149 if crate::thread::panicking() {
150 fail_aborting(e, msg)
151 } else {
152 panic!("{} failed: {}", *msg, e)
153 }
154 }
155
156 #[cold]
fail_aborting(e: impl fmt::Display, msg: &&str) -> !157 pub fn fail_aborting(e: impl fmt::Display, msg: &&str) -> ! {
158 rtabort!("{} failed: {}", *msg, e)
159 }
160