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