Skip to main content

ax_api/
lib.rs

1//! Public APIs and types for [ArceOS] modules
2//!
3//! [ArceOS]: https://github.com/arceos-org/arceos
4
5#![no_std]
6#![allow(unused_imports)]
7
8extern crate alloc;
9
10#[macro_use]
11mod macros;
12mod error;
13mod imp;
14
15pub use error::{ApiError, ApiResult};
16
17/// Platform-specific constants and parameters.
18pub mod config {
19    /// Stack size used when callers do not provide an explicit task stack.
20    pub const TASK_STACK_SIZE: usize = 0x40000;
21}
22
23/// System operations.
24pub mod sys {
25    define_api! {
26        /// Returns the number of available logical CPUs.
27        pub fn ax_get_cpu_num() -> usize;
28        /// Drain task-console output, then shut down the whole system and all CPUs.
29        pub fn ax_terminate() -> !;
30    }
31}
32
33/// Time-related operations.
34pub mod time {
35    define_api_type! {
36        pub type AxTimeValue;
37    }
38
39    define_api! {
40        /// Returns the time elapsed since system boot.
41        pub fn ax_monotonic_time() -> AxTimeValue;
42        /// Returns the time elapsed since epoch, also known as realtime.
43        pub fn ax_wall_time() -> AxTimeValue;
44    }
45}
46
47/// Memory management.
48pub mod mem {
49    use core::{alloc::Layout, ptr::NonNull};
50
51    define_api! {
52        @cfg "alloc";
53        /// Allocates a continuous memory blocks with the given `layout` in
54        /// the global allocator.
55        ///
56        /// Returns [`None`] if the allocation fails.
57        ///
58        /// # Safety
59        ///
60        /// This function is unsafe because it requires users to manually manage
61        /// the buffer life cycle.
62        pub unsafe fn ax_alloc(layout: Layout) -> Option<NonNull<u8>>;
63        /// Deallocates the memory block at the given `ptr` pointer with the given
64        /// `layout`, which should be allocated by [`ax_alloc`].
65        ///
66        /// # Safety
67        ///
68        /// This function is unsafe because it requires users to manually manage
69        /// the buffer life cycle.
70        pub unsafe fn ax_dealloc(ptr: NonNull<u8>, layout: Layout);
71    }
72}
73
74/// Standard input and output.
75pub mod stdio {
76    use core::fmt;
77    define_api! {
78        /// Reads a slice of bytes from the console, returns the number of bytes read.
79        pub fn ax_console_read_bytes(buf: &mut [u8]) -> crate::ApiResult<usize>;
80        /// Writes a slice of bytes to the console, returns the number of bytes written.
81        pub fn ax_console_write_bytes(buf: &[u8]) -> crate::ApiResult<usize>;
82        /// Writes a formatted string through the sleepable TTY console path.
83        pub fn ax_console_write_fmt(args: fmt::Arguments) -> fmt::Result;
84        /// Sleeps until task-console input becomes readable.
85        pub fn ax_console_wait_readable() -> crate::ApiResult;
86        /// Drains queued task output through the physical UART.
87        pub fn ax_console_flush() -> crate::ApiResult;
88    }
89}
90
91/// Multi-threading management.
92pub mod task {
93    define_api_type! {
94        pub type AxTaskHandle;
95        pub type AxWaitQueueHandle;
96        pub type AxCpuMask;
97        pub type AxRawMutex;
98    }
99
100    define_api! {
101        /// Current task is going to sleep, it will be woken up at the given monotonic deadline.
102        #[track_caller]
103        pub fn ax_sleep_until(deadline: crate::time::AxTimeValue);
104
105        /// Current task gives up the CPU time voluntarily, and switches to another
106        /// ready task.
107        #[track_caller]
108        pub fn ax_yield_now();
109
110        /// Exits the current task with the given exit code.
111        #[track_caller]
112        pub fn ax_exit(exit_code: i32) -> !;
113    }
114
115    define_api! {
116        /// Returns the current task's ID.
117        pub fn ax_current_task_id() -> u64;
118        /// Spawns a new task with the given entry point and other arguments.
119        pub fn ax_spawn(
120            f: impl FnOnce() + Send + 'static,
121            name: alloc::string::String,
122            stack_size: usize
123        ) -> AxTaskHandle;
124        /// Waits for the given task to exit, and returns its exit code (the
125        /// argument of [`ax_exit`]).
126        #[track_caller]
127        pub fn ax_wait_for_exit(task: AxTaskHandle) -> i32;
128        /// Sets the priority of the current task.
129        pub fn ax_set_current_priority(prio: isize) -> crate::ApiResult;
130        /// Sets the cpu affinity of the current task.
131        #[track_caller]
132        pub fn ax_set_current_affinity(cpumask: AxCpuMask) -> crate::ApiResult;
133        /// Blocks the current task and put it into the wait queue, until
134        /// other tasks notify the wait queue, or the given duration has
135        /// elapsed (if specified).
136        #[track_caller]
137        pub fn ax_wait_queue_wait(wq: &AxWaitQueueHandle, timeout: Option<core::time::Duration>) -> bool;
138        /// Blocks the current task and put it into the wait queue, until the
139        /// given condition becomes true, or the given duration has elapsed
140        /// (if specified).
141        #[track_caller]
142        pub fn ax_wait_queue_wait_until(
143            wq: &AxWaitQueueHandle,
144            until_condition: impl Fn() -> bool,
145            timeout: Option<core::time::Duration>,
146        ) -> bool;
147        /// Wakes up one or more tasks in the wait queue.
148        ///
149        /// The maximum number of tasks to wake up is specified by `count`. If
150        /// `count` is `u32::MAX`, it will wake up all tasks in the wait queue.
151        pub fn ax_wait_queue_wake(wq: &AxWaitQueueHandle, count: u32);
152        /// Wakes up at most one task in the wait queue after performing an
153        /// operation on it via the provided callback `func`.
154        ///
155        /// The callback `func` is invoked while holding the wait-queue lock. If a
156        /// task is woken, `func` is called with an implementation-defined `u64`
157        /// value associated with that task.
158        pub fn ax_wait_queue_wake_one_with(wq: &AxWaitQueueHandle, func: impl Fn(u64));
159    }
160}
161
162/// Filesystem manipulation operations.
163pub mod fs {
164    use crate::ApiResult;
165
166    define_api_type! {
167        @cfg "fs";
168        pub type AxFileHandle;
169        pub type AxDirHandle;
170        pub type AxOpenOptions;
171        pub type AxFileAttr;
172        pub type AxFileType;
173        pub type AxFileTypeExt;
174        pub type AxFilePerm;
175        pub type AxFilePermExt;
176        pub type AxDirEntry;
177        pub type AxSeekFrom;
178    }
179
180    define_api! {
181        @cfg "fs";
182
183        /// Opens a file at the path relative to the current directory with the
184        /// options specified by `opts`.
185        pub fn ax_open_file(path: &str, opts: &AxOpenOptions) -> ApiResult<AxFileHandle>;
186        /// Opens a directory at the path relative to the current directory with
187        /// the options specified by `opts`.
188        pub fn ax_open_dir(path: &str, opts: &AxOpenOptions) -> ApiResult<AxDirHandle>;
189
190        /// Reads the file at the current position, returns the number of bytes read.
191        ///
192        /// After the read, the cursor will be advanced by the number of bytes read.
193        pub fn ax_read_file(file: &mut AxFileHandle, buf: &mut [u8]) -> ApiResult<usize>;
194        /// Reads the file at the given position, returns the number of bytes read.
195        ///
196        /// It does not update the file cursor.
197        pub fn ax_read_file_at(file: &AxFileHandle, offset: u64, buf: &mut [u8]) -> ApiResult<usize>;
198        /// Writes the file at the current position, returns the number of bytes
199        /// written.
200        ///
201        /// After the write, the cursor will be advanced by the number of bytes
202        /// written.
203        pub fn ax_write_file(file: &mut AxFileHandle, buf: &[u8]) -> ApiResult<usize>;
204        /// Writes the file at the given position, returns the number of bytes
205        /// written.
206        ///
207        /// It does not update the file cursor.
208        pub fn ax_write_file_at(file: &AxFileHandle, offset: u64, buf: &[u8]) -> ApiResult<usize>;
209        /// Truncates the file to the specified size.
210        pub fn ax_truncate_file(file: &AxFileHandle, size: u64) -> ApiResult;
211        /// Flushes the file, writes all buffered data to the underlying device.
212        pub fn ax_flush_file(file: &AxFileHandle) -> ApiResult;
213        /// Sets the cursor of the file to the specified offset. Returns the new
214        /// position after the seek.
215        pub fn ax_seek_file(file: &mut AxFileHandle, pos: AxSeekFrom) -> ApiResult<u64>;
216        /// Returns attributes of the file.
217        pub fn ax_file_attr(file: &AxFileHandle) -> ApiResult<AxFileAttr>;
218
219        /// Reads directory entries starts from the current position into the
220        /// given buffer, returns the number of entries read.
221        ///
222        /// After the read, the cursor of the directory will be advanced by the
223        /// number of entries read.
224        pub fn ax_read_dir(dir: &mut AxDirHandle, dirents: &mut [AxDirEntry]) -> ApiResult<usize>;
225        /// Creates a new, empty directory at the provided path.
226        pub fn ax_create_dir(path: &str) -> ApiResult;
227        /// Removes an empty directory.
228        ///
229        /// If the directory is not empty, it will return an error.
230        pub fn ax_remove_dir(path: &str) -> ApiResult;
231        /// Removes a file from the filesystem.
232        pub fn ax_remove_file(path: &str) -> ApiResult;
233        /// Rename a file or directory to a new name.
234        ///
235        /// It will delete the original file if `new` already exists.
236        pub fn ax_rename(old: &str, new: &str) -> ApiResult;
237
238        /// Returns the current working directory.
239        pub fn ax_current_dir() -> ApiResult<alloc::string::String>;
240        /// Changes the current working directory to the specified path.
241        pub fn ax_set_current_dir(path: &str) -> ApiResult;
242    }
243}
244
245/// Networking primitives for TCP/UDP communication.
246pub mod net {
247    use core::net::{IpAddr, SocketAddr};
248
249    use crate::{ApiResult, io::AxPollState};
250
251    define_api_type! {
252        @cfg "net";
253        pub type AxTcpSocketHandle;
254        pub type AxUdpSocketHandle;
255    }
256
257    define_api! {
258        @cfg "net";
259
260        // TCP socket
261
262        /// Creates a new TCP socket.
263        pub fn ax_tcp_socket() -> AxTcpSocketHandle;
264        /// Returns the local address and port of the TCP socket.
265        pub fn ax_tcp_socket_addr(socket: &AxTcpSocketHandle) -> ApiResult<SocketAddr>;
266        /// Returns the remote address and port of the TCP socket.
267        pub fn ax_tcp_peer_addr(socket: &AxTcpSocketHandle) -> ApiResult<SocketAddr>;
268        /// Moves this TCP socket into or out of nonblocking mode.
269        pub fn ax_tcp_set_nonblocking(socket: &AxTcpSocketHandle, nonblocking: bool) -> ApiResult;
270
271        /// Connects the TCP socket to the given address and port.
272        pub fn ax_tcp_connect(handle: &AxTcpSocketHandle, addr: SocketAddr) -> ApiResult;
273        /// Binds the TCP socket to the given address and port.
274        pub fn ax_tcp_bind(socket: &AxTcpSocketHandle, addr: SocketAddr) -> ApiResult;
275        /// Starts listening on the bound address and port.
276        pub fn ax_tcp_listen(socket: &AxTcpSocketHandle, _backlog: usize) -> ApiResult;
277        /// Accepts a new connection on the TCP socket.
278        ///
279        /// This function will block the calling thread until a new TCP connection
280        /// is established. When established, a new TCP socket is returned.
281        pub fn ax_tcp_accept(socket: &AxTcpSocketHandle) -> ApiResult<(AxTcpSocketHandle, SocketAddr)>;
282
283        /// Transmits data in the given buffer on the TCP socket.
284        pub fn ax_tcp_send(socket: &AxTcpSocketHandle, buf: &[u8]) -> ApiResult<usize>;
285        /// Receives data on the TCP socket, and stores it in the given buffer.
286        /// On success, returns the number of bytes read.
287        pub fn ax_tcp_recv(socket: &AxTcpSocketHandle, buf: &mut [u8]) -> ApiResult<usize>;
288        /// Returns whether the TCP socket is readable or writable.
289        pub fn ax_tcp_poll(socket: &AxTcpSocketHandle) -> ApiResult<AxPollState>;
290        /// Closes the connection on the TCP socket.
291        pub fn ax_tcp_shutdown(socket: &AxTcpSocketHandle) -> ApiResult;
292
293        // UDP socket
294
295        /// Creates a new UDP socket.
296        pub fn ax_udp_socket() -> AxUdpSocketHandle;
297        /// Returns the local address and port of the UDP socket.
298        pub fn ax_udp_socket_addr(socket: &AxUdpSocketHandle) -> ApiResult<SocketAddr>;
299        /// Returns the remote address and port of the UDP socket.
300        pub fn ax_udp_peer_addr(socket: &AxUdpSocketHandle) -> ApiResult<SocketAddr>;
301        /// Moves this UDP socket into or out of nonblocking mode.
302        pub fn ax_udp_set_nonblocking(socket: &AxUdpSocketHandle, nonblocking: bool) -> ApiResult;
303
304        /// Binds the UDP socket to the given address and port.
305        pub fn ax_udp_bind(socket: &AxUdpSocketHandle, addr: SocketAddr) -> ApiResult;
306        /// Receives a single datagram message on the UDP socket.
307        pub fn ax_udp_recv_from(socket: &AxUdpSocketHandle, buf: &mut [u8]) -> ApiResult<(usize, SocketAddr)>;
308        /// Receives a single datagram message on the UDP socket, without
309        /// removing it from the queue.
310        pub fn ax_udp_peek_from(socket: &AxUdpSocketHandle, buf: &mut [u8]) -> ApiResult<(usize, SocketAddr)>;
311        /// Sends data on the UDP socket to the given address. On success,
312        /// returns the number of bytes written.
313        pub fn ax_udp_send_to(socket: &AxUdpSocketHandle, buf: &[u8], addr: SocketAddr) -> ApiResult<usize>;
314
315        /// Connects this UDP socket to a remote address, allowing the `send` and
316        /// `recv` to be used to send data and also applies filters to only receive
317        /// data from the specified address.
318        pub fn ax_udp_connect(socket: &AxUdpSocketHandle, addr: SocketAddr) -> ApiResult;
319        /// Sends data on the UDP socket to the remote address to which it is
320        /// connected.
321        pub fn ax_udp_send(socket: &AxUdpSocketHandle, buf: &[u8]) -> ApiResult<usize>;
322        /// Receives a single datagram message on the UDP socket from the remote
323        /// address to which it is connected. On success, returns the number of
324        /// bytes read.
325        pub fn ax_udp_recv(socket: &AxUdpSocketHandle, buf: &mut [u8]) -> ApiResult<usize>;
326        /// Returns whether the UDP socket is readable or writable.
327        pub fn ax_udp_poll(socket: &AxUdpSocketHandle) -> ApiResult<AxPollState>;
328
329        // Miscellaneous
330
331        /// Resolves the host name to a list of IP addresses.
332        pub fn ax_dns_query(domain_name: &str) -> ApiResult<alloc::vec::Vec<IpAddr>>;
333        /// Poll the network stack.
334        ///
335        /// It may receive packets from the NIC and process them, and transmit queued
336        /// packets to the NIC.
337        pub fn ax_poll_interfaces() -> ApiResult;
338    }
339}
340
341/// Graphics manipulation operations.
342pub mod display {
343    define_api_type! {
344        @cfg "display";
345        pub type AxDisplayInfo;
346    }
347
348    define_api! {
349        @cfg "display";
350        /// Gets the framebuffer information.
351        pub fn ax_framebuffer_info() -> AxDisplayInfo;
352        /// Flushes the framebuffer, i.e. show on the screen.
353        pub fn ax_framebuffer_flush() -> bool;
354    }
355}
356
357/// Input/output operations.
358pub mod io {
359    define_api_type! {
360        pub type AxPollState;
361    }
362}
363
364/// Re-exports of ArceOS modules.
365///
366/// You should prefer to use other APIs rather than these modules. The modules
367/// here should only be used if other APIs do not meet your requirements.
368pub mod modules {
369    #[cfg(feature = "alloc")]
370    pub use ax_alloc;
371    #[cfg(feature = "display")]
372    pub use ax_display;
373    #[cfg(feature = "fs")]
374    pub use ax_fs_ng;
375    pub use ax_hal;
376    #[cfg(feature = "ipi")]
377    pub use ax_ipi;
378    pub use ax_log;
379    #[cfg(feature = "paging")]
380    pub use ax_mm;
381    #[cfg(feature = "net")]
382    pub use ax_net;
383    pub use ax_runtime;
384    pub use ax_task;
385    pub use axklib;
386    pub use dma_api;
387}