Skip to main content

ax_api/
error.rs

1#[cfg(feature = "fs")]
2use ax_fs_ng::VfsError;
3use ax_io::IoError;
4#[cfg(feature = "net")]
5use ax_net::NetError;
6use ax_runtime::{RuntimeError, task::thread::TaskError};
7
8/// Errors owned by the public ArceOS API facade.
9#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
10pub enum ApiError {
11    /// A filesystem API failed in the VFS domain.
12    #[cfg(feature = "fs")]
13    #[error(transparent)]
14    Vfs(#[from] VfsError),
15    /// A socket API failed in the network domain.
16    #[cfg(feature = "net")]
17    #[error(transparent)]
18    Net(#[from] NetError),
19    /// A runtime-owned console operation failed.
20    #[error(transparent)]
21    Runtime(#[from] RuntimeError),
22    /// A scheduler operation failed in the task domain.
23    #[error(transparent)]
24    Task(#[from] TaskError),
25    /// A public API argument is outside its accepted domain.
26    #[error("invalid ArceOS API input")]
27    InvalidInput,
28    /// The selected object or policy does not support this operation.
29    #[error("ArceOS API operation is not supported")]
30    OperationNotSupported,
31    /// The scheduler rejected a priority update.
32    #[error("failed to update the current task priority")]
33    PriorityUpdateFailed,
34    /// The scheduler rejected an affinity update.
35    #[error("failed to update the current task affinity")]
36    AffinityUpdateFailed,
37}
38
39/// A result returned by the public ArceOS API facade.
40pub type ApiResult<T = ()> = Result<T, ApiError>;
41
42impl From<ApiError> for IoError {
43    fn from(error: ApiError) -> Self {
44        match error {
45            #[cfg(feature = "fs")]
46            ApiError::Vfs(error) => vfs_error_to_io_error(error),
47            #[cfg(feature = "net")]
48            ApiError::Net(error) => error.into(),
49            ApiError::Runtime(error) => runtime_error_to_io_error(error),
50            ApiError::Task(error) => task_error_to_io_error(error),
51            ApiError::InvalidInput => Self::InvalidInput,
52            ApiError::OperationNotSupported => Self::OperationNotSupported,
53            ApiError::PriorityUpdateFailed | ApiError::AffinityUpdateFailed => Self::BadState,
54        }
55    }
56}
57fn task_error_to_io_error(error: TaskError) -> IoError {
58    match error {
59        TaskError::InvalidConfiguration
60        | TaskError::InvalidCpuCount(_)
61        | TaskError::InvalidCpu(_)
62        | TaskError::InvalidNice(_)
63        | TaskError::InvalidRtPriority(_)
64        | TaskError::InvalidRoundRobinQuantum
65        | TaskError::InvalidDeadline { .. }
66        | TaskError::UnsupportedDeadlineFlags(_) => IoError::InvalidInput,
67        TaskError::DeadlineAdmission
68        | TaskError::DeadlineAffinity
69        | TaskError::ActiveTimerAffinity
70        | TaskError::ThreadBusy => IoError::ResourceBusy,
71        // Linux copy_process() reports the global thread limit as EAGAIN.
72        TaskError::ThreadCapacity => IoError::WouldBlock,
73        TaskError::TimerCapacity => IoError::NoMemory,
74        TaskError::RuntimeFailure(status)
75            if status == ax_runtime::task::runtime::RuntimeStatus::NoMemory as u32 =>
76        {
77            IoError::NoMemory
78        }
79        TaskError::UnsafeContext => IoError::OperationNotPermitted,
80        TaskError::StaleThreadId => IoError::NotFound,
81        TaskError::NotInitialized
82        | TaskError::InvalidRuntimeHandle
83        | TaskError::CpuOwnerBorrowed
84        | TaskError::CpuOwnerMismatch { .. }
85        | TaskError::ExecutorOwnerMismatch { .. }
86        | TaskError::CpuAlreadyOnline(_)
87        | TaskError::CpuOffline(_)
88        | TaskError::CpuNotQuiescent(_)
89        | TaskError::LastOnlineCpu(_)
90        | TaskError::InvalidTransition { .. }
91        | TaskError::AlreadyQueued
92        | TaskError::NotReady
93        | TaskError::NotExited
94        | TaskError::NoRunnableThread
95        | TaskError::InvalidPiState
96        | TaskError::InvalidPiWaitState(_)
97        | TaskError::PiCycle
98        | TaskError::PiChainLimit { .. }
99        | TaskError::RuntimeFailure(_) => IoError::BadState,
100    }
101}
102
103#[cfg(feature = "fs")]
104fn vfs_error_to_io_error(error: VfsError) -> IoError {
105    match error {
106        VfsError::AlreadyExists => IoError::AlreadyExists,
107        VfsError::BadAddress => IoError::BadAddress,
108        VfsError::BadFileDescriptor => IoError::BadFileDescriptor,
109        VfsError::BadState => IoError::BadState,
110        VfsError::CrossesDevices => IoError::CrossesDevices,
111        // These VFS categories have no exact `ax-io` representation. Keep
112        // them exact for VFS/POSIX callers and degrade only at this facade.
113        VfsError::DataMissing => IoError::InvalidData,
114        VfsError::DirectoryNotEmpty => IoError::DirectoryNotEmpty,
115        VfsError::FilesystemCorrupted => IoError::InvalidData,
116        VfsError::FilesystemLoop => IoError::FilesystemLoop,
117        VfsError::FileTooLarge => IoError::FileTooLarge,
118        VfsError::InvalidData => IoError::InvalidData,
119        VfsError::InvalidInput => IoError::InvalidInput,
120        VfsError::Interrupted => IoError::Interrupted,
121        VfsError::Io => IoError::Io,
122        VfsError::IsADirectory => IoError::IsADirectory,
123        VfsError::NameTooLong => IoError::NameTooLong,
124        VfsError::NoMemory => IoError::NoMemory,
125        VfsError::NoSuchDevice => IoError::NoSuchDevice,
126        VfsError::NoSuchDeviceOrAddress => IoError::NoSuchDeviceOrAddress,
127        VfsError::NotADirectory => IoError::NotADirectory,
128        VfsError::NotATty => IoError::NotATty,
129        VfsError::NotFound => IoError::NotFound,
130        VfsError::OperationNotPermitted => IoError::OperationNotPermitted,
131        VfsError::OperationNotSupported => IoError::OperationNotSupported,
132        VfsError::PermissionDenied => IoError::PermissionDenied,
133        VfsError::QuotaExceeded => IoError::StorageFull,
134        VfsError::ReadOnlyFilesystem => IoError::ReadOnlyFilesystem,
135        VfsError::ResourceBusy => IoError::ResourceBusy,
136        VfsError::StorageFull => IoError::StorageFull,
137        VfsError::TimedOut => IoError::TimedOut,
138        VfsError::TooManyLinks => IoError::Io,
139        VfsError::Unsupported => IoError::Unsupported,
140        VfsError::ValueOverflow => IoError::OutOfRange,
141        VfsError::WouldBlock => IoError::WouldBlock,
142    }
143}
144
145fn runtime_error_to_io_error(error: RuntimeError) -> IoError {
146    match error {
147        RuntimeError::ConsoleFailedClosed => IoError::BadState,
148        RuntimeError::SerialNotStarted => IoError::BadState,
149        RuntimeError::SerialControlBusy => IoError::ResourceBusy,
150        RuntimeError::WouldBlock => IoError::WouldBlock,
151        RuntimeError::OperationNotSupported => IoError::OperationNotSupported,
152        RuntimeError::InvalidCpu { .. } => IoError::InvalidInput,
153        _ => IoError::Io,
154    }
155}