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