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