arceos_api/imp/
task.rs

1pub fn ax_sleep_until(deadline: crate::time::AxTimeValue) {
2    #[cfg(feature = "multitask")]
3    axtask::sleep_until(deadline);
4    #[cfg(not(feature = "multitask"))]
5    axhal::time::busy_wait_until(deadline);
6}
7
8pub fn ax_yield_now() {
9    #[cfg(feature = "multitask")]
10    axtask::yield_now();
11    #[cfg(not(feature = "multitask"))]
12    if cfg!(feature = "irq") {
13        axhal::arch::wait_for_irqs();
14    } else {
15        core::hint::spin_loop();
16    }
17}
18
19pub fn ax_exit(_exit_code: i32) -> ! {
20    #[cfg(feature = "multitask")]
21    axtask::exit(_exit_code);
22    #[cfg(not(feature = "multitask"))]
23    axhal::misc::terminate();
24}
25
26cfg_task! {
27    use core::time::Duration;
28
29    /// A handle to a task.
30    pub struct AxTaskHandle {
31        inner: axtask::AxTaskRef,
32        id: u64,
33    }
34
35    impl AxTaskHandle {
36        /// Returns the task ID.
37        pub fn id(&self) -> u64 {
38            self.id
39        }
40    }
41
42    /// A mask to specify the CPU affinity.
43    pub use axtask::AxCpuMask;
44
45    /// A handle to a wait queue.
46    ///
47    /// A wait queue is used to store sleeping tasks waiting for a certain event
48    /// to happen.
49    pub struct AxWaitQueueHandle(axtask::WaitQueue);
50
51    impl AxWaitQueueHandle {
52        /// Creates a new empty wait queue.
53        pub const fn new() -> Self {
54            Self(axtask::WaitQueue::new())
55        }
56    }
57
58    pub fn ax_current_task_id() -> u64 {
59        axtask::current().id().as_u64()
60    }
61
62    pub fn ax_spawn<F>(f: F, name: alloc::string::String, stack_size: usize) -> AxTaskHandle
63    where
64        F: FnOnce() + Send + 'static,
65    {
66        let inner = axtask::spawn_raw(f, name, stack_size);
67        AxTaskHandle {
68            id: inner.id().as_u64(),
69            inner,
70        }
71    }
72
73    pub fn ax_wait_for_exit(task: AxTaskHandle) -> Option<i32> {
74        task.inner.join()
75    }
76
77    pub fn ax_set_current_priority(prio: isize) -> crate::AxResult {
78        if axtask::set_priority(prio) {
79            Ok(())
80        } else {
81            axerrno::ax_err!(
82                BadState,
83                "ax_set_current_priority: failed to set task priority"
84            )
85        }
86    }
87
88    pub fn ax_set_current_affinity(cpumask: AxCpuMask) -> crate::AxResult {
89        if axtask::set_current_affinity(cpumask) {
90            Ok(())
91        } else {
92            axerrno::ax_err!(
93                BadState,
94                "ax_set_current_affinity: failed to set task affinity"
95            )
96        }
97    }
98
99    pub fn ax_wait_queue_wait(wq: &AxWaitQueueHandle, timeout: Option<Duration>) -> bool {
100        #[cfg(feature = "irq")]
101        if let Some(dur) = timeout {
102            return wq.0.wait_timeout(dur);
103        }
104
105        if timeout.is_some() {
106            axlog::warn!("ax_wait_queue_wait: the `timeout` argument is ignored without the `irq` feature");
107        }
108        wq.0.wait();
109        false
110    }
111
112    pub fn ax_wait_queue_wait_until(
113        wq: &AxWaitQueueHandle,
114        until_condition: impl Fn() -> bool,
115        timeout: Option<Duration>,
116    ) -> bool {
117        #[cfg(feature = "irq")]
118        if let Some(dur) = timeout {
119            return wq.0.wait_timeout_until(dur, until_condition);
120        }
121
122        if timeout.is_some() {
123            axlog::warn!("ax_wait_queue_wait_until: the `timeout` argument is ignored without the `irq` feature");
124        }
125        wq.0.wait_until(until_condition);
126        false
127    }
128
129    pub fn ax_wait_queue_wake(wq: &AxWaitQueueHandle, count: u32) {
130        if count == u32::MAX {
131            wq.0.notify_all(true);
132        } else {
133            for _ in 0..count {
134                wq.0.notify_one(true);
135            }
136        }
137    }
138}