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