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