Skip to main content

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