sel4_microkit_base/
handler.rs1use core::fmt;
8
9#[cfg(feature = "alloc")]
10use alloc::boxed::Box;
11
12use crate::{
13 Channel, Child, MessageInfo,
14 defer::{DeferredAction, PreparedDeferredAction},
15 ipc::{self, ChannelSet, Event},
16 pd_is_passive,
17};
18
19pub use core::convert::Infallible;
20
21pub trait Handler {
23 type Error: fmt::Display;
25
26 fn notified(&mut self, channels: ChannelSet) -> Result<(), Self::Error> {
30 panic!(
31 "unexpected notification from channels {}",
32 channels.display()
33 )
34 }
35
36 fn protected(
40 &mut self,
41 channel: Channel,
42 msg_info: MessageInfo,
43 ) -> Result<MessageInfo, Self::Error> {
44 panic!(
45 "unexpected protected procedure call from channel {channel:?} with msg_info={msg_info:?}"
46 )
47 }
48
49 fn fault(
53 &mut self,
54 child: Child,
55 msg_info: MessageInfo,
56 ) -> Result<Option<MessageInfo>, Self::Error> {
57 panic!("unexpected fault from protection domain {child:?} with msg_info={msg_info:?}")
58 }
59
60 fn take_deferred_action(&mut self) -> Option<DeferredAction> {
66 None
67 }
68
69 #[doc(hidden)]
70 fn run(&mut self) -> Result<Never, Self::Error> {
71 let mut reply_tag: Option<MessageInfo> = None;
72
73 let mut prepared_deferred_action: Option<PreparedDeferredAction> = if pd_is_passive() {
74 Some(ipc::forfeit_sc())
75 } else {
76 None
77 };
78
79 loop {
80 let event = match (reply_tag.take(), prepared_deferred_action.take()) {
81 (Some(msg_info), None) => ipc::reply_recv(msg_info),
82 (None, Some(action)) => ipc::nb_send_recv(action),
83 (None, None) => ipc::recv(),
84 _ => panic!("handler yielded deferred action after call to 'protected()'"),
85 };
86
87 match event {
88 Event::Notified(channels) => {
89 self.notified(channels)?;
90 }
91 Event::Protected(channel, msg_info) => {
92 reply_tag = Some(self.protected(channel, msg_info)?);
93 }
94 Event::Fault(child, msg_info) => {
95 reply_tag = self.fault(child, msg_info)?;
96 }
97 };
98
99 prepared_deferred_action = self
100 .take_deferred_action()
101 .as_ref()
102 .map(DeferredAction::prepare);
103 }
104 }
105}
106
107#[doc(hidden)]
108pub enum Never {}
109
110impl Handler for Never {
111 type Error = Infallible;
112}
113
114pub struct NullHandler(());
116
117impl NullHandler {
118 #[allow(clippy::new_without_default)]
119 pub fn new() -> Self {
120 Self(())
121 }
122}
123
124impl Handler for NullHandler {
125 type Error = Infallible;
126}
127
128#[cfg(feature = "alloc")]
129impl<T: Handler + ?Sized> Handler for Box<T> {
130 type Error = T::Error;
131
132 fn notified(&mut self, channels: ChannelSet) -> Result<(), Self::Error> {
133 (**self).notified(channels)
134 }
135
136 fn protected(
137 &mut self,
138 channel: Channel,
139 msg_info: MessageInfo,
140 ) -> Result<MessageInfo, Self::Error> {
141 (**self).protected(channel, msg_info)
142 }
143
144 fn fault(
145 &mut self,
146 child: Child,
147 msg_info: MessageInfo,
148 ) -> Result<Option<MessageInfo>, Self::Error> {
149 (**self).fault(child, msg_info)
150 }
151
152 fn take_deferred_action(&mut self) -> Option<DeferredAction> {
153 (**self).take_deferred_action()
154 }
155
156 #[doc(hidden)]
157 fn run(&mut self) -> Result<Never, Self::Error> {
158 (**self).run()
159 }
160}