1use ax_lazyinit::OnceLock;
2use ax_task::{
3 sync::irq::{IrqWaitCell, IrqWorkerWaiter},
4 thread::{TaskError, ThreadId, current::current_thread_handle},
5};
6
7pub struct FixedIrqWorkerSignal {
13 doorbell: IrqWaitCell,
14 waiter: OnceLock<FixedIrqWorkerWaiter>,
15}
16
17impl FixedIrqWorkerSignal {
18 pub const fn new() -> Self {
19 Self {
20 doorbell: IrqWaitCell::new(),
21 waiter: OnceLock::new(),
22 }
23 }
24
25 pub fn notify(&self) {
28 let _result = self.doorbell.notify();
29 }
30
31 pub fn wait(&self) -> Result<(), TaskError> {
33 let current = current_thread_handle()?;
34 let waiter = self.waiter.call_once(|| FixedIrqWorkerWaiter {
35 owner: current.id(),
36 irq: IrqWorkerWaiter::new(current.wake_handle()),
37 });
38 if waiter.owner != current.id() {
39 return Err(TaskError::InvalidConfiguration);
40 }
41 waiter.irq.wait(&self.doorbell)
42 }
43
44 #[cfg(test)]
45 pub(crate) fn is_pending(&self) -> bool {
46 self.doorbell.is_pending()
47 }
48}
49
50impl Default for FixedIrqWorkerSignal {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56struct FixedIrqWorkerWaiter {
57 owner: ThreadId,
58 irq: IrqWorkerWaiter,
59}