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 /// Blocks until the condition becomes true or an absolute monotonic
148 /// deadline elapses. Returns `true` only when the deadline wins.
149 #[track_caller]
150 pub fn ax_wait_queue_wait_until_deadline(
151 wq: &AxWaitQueueHandle,
152 deadline: core::time::Duration,
153 until_condition: impl Fn() -> bool,
154 ) -> bool;
155 /// Wakes up one or more tasks in the wait queue.
156 ///
157 /// The maximum number of tasks to wake up is specified by `count`. If
158 /// `count` is `u32::MAX`, it will wake up all tasks in the wait queue.
159 /// Returns the number of waiters selected for wakeup.
160 pub fn ax_wait_queue_wake(wq: &AxWaitQueueHandle, count: u32) -> usize;
161 }
162}
163
164/// Filesystem manipulation operations.
165pub mod fs {
166 use crate::ApiResult;
167
168 define_api_type! {
169 @cfg "fs";
170 pub type AxFileHandle;
171 pub type AxDirHandle;
172 pub type AxOpenOptions;
173 pub type AxFileAttr;
174 pub type AxFileType;
175 pub type AxFileTypeExt;
176 pub type AxFilePerm;
177 pub type AxFilePermExt;
178 pub type AxDirEntry;
179 pub type AxSeekFrom;
180 }
181
182 define_api! {
183 @cfg "fs";
184
185 /// Opens a file at the path relative to the current directory with the
186 /// options specified by `opts`.
187 pub fn ax_open_file(path: &str, opts: &AxOpenOptions) -> ApiResult<AxFileHandle>;
188 /// Opens a directory at the path relative to the current directory with
189 /// the options specified by `opts`.
190 pub fn ax_open_dir(path: &str, opts: &AxOpenOptions) -> ApiResult<AxDirHandle>;
191
192 /// Reads the file at the current position, returns the number of bytes read.
193 ///
194 /// After the read, the cursor will be advanced by the number of bytes read.
195 pub fn ax_read_file(file: &mut AxFileHandle, buf: &mut [u8]) -> ApiResult<usize>;
196 /// Reads the file at the given position, returns the number of bytes read.
197 ///
198 /// It does not update the file cursor.
199 pub fn ax_read_file_at(file: &AxFileHandle, offset: u64, buf: &mut [u8]) -> ApiResult<usize>;
200 /// Writes the file at the current position, returns the number of bytes
201 /// written.
202 ///
203 /// After the write, the cursor will be advanced by the number of bytes
204 /// written.
205 pub fn ax_write_file(file: &mut AxFileHandle, buf: &[u8]) -> ApiResult<usize>;
206 /// Writes the file at the given position, returns the number of bytes
207 /// written.
208 ///
209 /// It does not update the file cursor.
210 pub fn ax_write_file_at(file: &AxFileHandle, offset: u64, buf: &[u8]) -> ApiResult<usize>;
211 /// Truncates the file to the specified size.
212 pub fn ax_truncate_file(file: &AxFileHandle, size: u64) -> ApiResult;
213 /// Flushes the file, writes all buffered data to the underlying device.
214 pub fn ax_flush_file(file: &AxFileHandle) -> ApiResult;
215 /// Sets the cursor of the file to the specified offset. Returns the new
216 /// position after the seek.
217 pub fn ax_seek_file(file: &mut AxFileHandle, pos: AxSeekFrom) -> ApiResult<u64>;
218 /// Returns attributes of the file.
219 pub fn ax_file_attr(file: &AxFileHandle) -> ApiResult<AxFileAttr>;
220
221 /// Reads directory entries starts from the current position into the
222 /// given buffer, returns the number of entries read.
223 ///
224 /// After the read, the cursor of the directory will be advanced by the
225 /// number of entries read.
226 pub fn ax_read_dir(dir: &mut AxDirHandle, dirents: &mut [AxDirEntry]) -> ApiResult<usize>;
227 /// Creates a new, empty directory at the provided path.
228 pub fn ax_create_dir(path: &str) -> ApiResult;
229 /// Removes an empty directory.
230 ///
231 /// If the directory is not empty, it will return an error.
232 pub fn ax_remove_dir(path: &str) -> ApiResult;
233 /// Removes a file from the filesystem.
234 pub fn ax_remove_file(path: &str) -> ApiResult;
235 /// Rename a file or directory to a new name.
236 ///
237 /// It will delete the original file if `new` already exists.
238 pub fn ax_rename(old: &str, new: &str) -> ApiResult;
239
240 /// Returns the current working directory.
241 pub fn ax_current_dir() -> ApiResult<alloc::string::String>;
242 /// Changes the current working directory to the specified path.
243 pub fn ax_set_current_dir(path: &str) -> ApiResult;
244 }
245}
246
247/// Networking primitives for TCP/UDP communication.
248pub mod net {
249 use core::net::{IpAddr, SocketAddr};
250
251 use crate::{ApiResult, io::AxPollState};
252
253 define_api_type! {
254 @cfg "net";
255 pub type AxTcpSocketHandle;
256 pub type AxUdpSocketHandle;
257 }
258
259 define_api! {
260 @cfg "net";
261
262 // TCP socket
263
264 /// Creates a new TCP socket.
265 pub fn ax_tcp_socket() -> AxTcpSocketHandle;
266 /// Returns the local address and port of the TCP socket.
267 pub fn ax_tcp_socket_addr(socket: &AxTcpSocketHandle) -> ApiResult<SocketAddr>;
268 /// Returns the remote address and port of the TCP socket.
269 pub fn ax_tcp_peer_addr(socket: &AxTcpSocketHandle) -> ApiResult<SocketAddr>;
270 /// Moves this TCP socket into or out of nonblocking mode.
271 pub fn ax_tcp_set_nonblocking(socket: &AxTcpSocketHandle, nonblocking: bool) -> ApiResult;
272
273 /// Connects the TCP socket to the given address and port.
274 pub fn ax_tcp_connect(handle: &AxTcpSocketHandle, addr: SocketAddr) -> ApiResult;
275 /// Binds the TCP socket to the given address and port.
276 pub fn ax_tcp_bind(socket: &AxTcpSocketHandle, addr: SocketAddr) -> ApiResult;
277 /// Starts listening on the bound address and port.
278 pub fn ax_tcp_listen(socket: &AxTcpSocketHandle, _backlog: usize) -> ApiResult;
279 /// Accepts a new connection on the TCP socket.
280 ///
281 /// This function will block the calling thread until a new TCP connection
282 /// is established. When established, a new TCP socket is returned.
283 pub fn ax_tcp_accept(socket: &AxTcpSocketHandle) -> ApiResult<(AxTcpSocketHandle, SocketAddr)>;
284
285 /// Transmits data in the given buffer on the TCP socket.
286 pub fn ax_tcp_send(socket: &AxTcpSocketHandle, buf: &[u8]) -> ApiResult<usize>;
287 /// Receives data on the TCP socket, and stores it in the given buffer.
288 /// On success, returns the number of bytes read.
289 pub fn ax_tcp_recv(socket: &AxTcpSocketHandle, buf: &mut [u8]) -> ApiResult<usize>;
290 /// Returns whether the TCP socket is readable or writable.
291 pub fn ax_tcp_poll(socket: &AxTcpSocketHandle) -> ApiResult<AxPollState>;
292 /// Closes the connection on the TCP socket.
293 pub fn ax_tcp_shutdown(socket: &AxTcpSocketHandle) -> ApiResult;
294
295 // UDP socket
296
297 /// Creates a new UDP socket.
298 pub fn ax_udp_socket() -> AxUdpSocketHandle;
299 /// Returns the local address and port of the UDP socket.
300 pub fn ax_udp_socket_addr(socket: &AxUdpSocketHandle) -> ApiResult<SocketAddr>;
301 /// Returns the remote address and port of the UDP socket.
302 pub fn ax_udp_peer_addr(socket: &AxUdpSocketHandle) -> ApiResult<SocketAddr>;
303 /// Moves this UDP socket into or out of nonblocking mode.
304 pub fn ax_udp_set_nonblocking(socket: &AxUdpSocketHandle, nonblocking: bool) -> ApiResult;
305
306 /// Binds the UDP socket to the given address and port.
307 pub fn ax_udp_bind(socket: &AxUdpSocketHandle, addr: SocketAddr) -> ApiResult;
308 /// Receives a single datagram message on the UDP socket.
309 pub fn ax_udp_recv_from(socket: &AxUdpSocketHandle, buf: &mut [u8]) -> ApiResult<(usize, SocketAddr)>;
310 /// Receives a single datagram message on the UDP socket, without
311 /// removing it from the queue.
312 pub fn ax_udp_peek_from(socket: &AxUdpSocketHandle, buf: &mut [u8]) -> ApiResult<(usize, SocketAddr)>;
313 /// Sends data on the UDP socket to the given address. On success,
314 /// returns the number of bytes written.
315 pub fn ax_udp_send_to(socket: &AxUdpSocketHandle, buf: &[u8], addr: SocketAddr) -> ApiResult<usize>;
316
317 /// Connects this UDP socket to a remote address, allowing the `send` and
318 /// `recv` to be used to send data and also applies filters to only receive
319 /// data from the specified address.
320 pub fn ax_udp_connect(socket: &AxUdpSocketHandle, addr: SocketAddr) -> ApiResult;
321 /// Sends data on the UDP socket to the remote address to which it is
322 /// connected.
323 pub fn ax_udp_send(socket: &AxUdpSocketHandle, buf: &[u8]) -> ApiResult<usize>;
324 /// Receives a single datagram message on the UDP socket from the remote
325 /// address to which it is connected. On success, returns the number of
326 /// bytes read.
327 pub fn ax_udp_recv(socket: &AxUdpSocketHandle, buf: &mut [u8]) -> ApiResult<usize>;
328 /// Returns whether the UDP socket is readable or writable.
329 pub fn ax_udp_poll(socket: &AxUdpSocketHandle) -> ApiResult<AxPollState>;
330
331 // Miscellaneous
332
333 /// Resolves the host name to a list of IP addresses.
334 pub fn ax_dns_query(domain_name: &str) -> ApiResult<alloc::vec::Vec<IpAddr>>;
335 }
336}
337
338/// Graphics manipulation operations.
339pub mod display {
340 define_api_type! {
341 @cfg "display";
342 pub type AxDisplayInfo;
343 }
344
345 define_api! {
346 @cfg "display";
347 /// Gets the framebuffer information.
348 pub fn ax_framebuffer_info() -> AxDisplayInfo;
349 /// Flushes the framebuffer, i.e. show on the screen.
350 pub fn ax_framebuffer_flush() -> bool;
351 }
352}
353
354/// Input/output operations.
355pub mod io {
356 define_api_type! {
357 pub type AxPollState;
358 }
359}
360
361/// Re-exports of ArceOS modules.
362///
363/// You should prefer to use other APIs rather than these modules. The modules
364/// here should only be used if other APIs do not meet your requirements.
365pub mod modules {
366 #[cfg(feature = "alloc")]
367 pub use ax_alloc;
368 #[cfg(feature = "display")]
369 pub use ax_display;
370 #[cfg(feature = "fs")]
371 pub use ax_fs_ng;
372 pub use ax_hal;
373 #[cfg(feature = "ipi")]
374 pub use ax_ipi;
375 pub use ax_log;
376 #[cfg(feature = "paging")]
377 pub use ax_mm;
378 #[cfg(feature = "net")]
379 pub use ax_net;
380 pub use ax_runtime;
381 pub use ax_task;
382 pub use axklib;
383 pub use dma_api;
384}