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