1use crate::{
8 ok, sys, AsHandleRef, BootTimeline, Handle, HandleBased, HandleRef, Instant, MonotonicTimeline,
9 Port, Status, Timeline,
10};
11use std::marker::PhantomData;
12
13#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
17#[repr(transparent)]
18pub struct Interrupt<K = RealInterruptKind, T = BootTimeline>(Handle, PhantomData<(K, T)>);
19
20pub trait InterruptKind: private::Sealed {}
21
22#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
23pub struct VirtualInterruptKind;
24
25impl InterruptKind for VirtualInterruptKind {}
26impl private::Sealed for VirtualInterruptKind {}
27
28#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
29pub struct RealInterruptKind;
30
31impl InterruptKind for RealInterruptKind {}
32impl private::Sealed for RealInterruptKind {}
33
34pub type VirtualInterrupt = Interrupt<VirtualInterruptKind>;
35
36impl<K: InterruptKind, T: Timeline> Interrupt<K, T> {
37 pub fn bind_port(&self, port: &Port, key: u64) -> Result<(), Status> {
41 let options = sys::ZX_INTERRUPT_BIND;
42 let status =
44 unsafe { sys::zx_interrupt_bind(self.raw_handle(), port.raw_handle(), key, options) };
45 ok(status)
46 }
47
48 pub fn ack(&self) -> Result<(), Status> {
52 let status = unsafe { sys::zx_interrupt_ack(self.raw_handle()) };
54 ok(status)
55 }
56}
57
58pub trait InterruptTimeline: Timeline {
59 const CREATE_FLAGS: u32;
60}
61
62impl InterruptTimeline for MonotonicTimeline {
63 const CREATE_FLAGS: u32 = sys::ZX_INTERRUPT_TIMESTAMP_MONO;
64}
65
66impl InterruptTimeline for BootTimeline {
67 const CREATE_FLAGS: u32 = 0;
68}
69
70impl<T: InterruptTimeline> Interrupt<VirtualInterruptKind, T> {
71 pub fn create_virtual() -> Result<Self, Status> {
75 let handle = unsafe {
77 let mut handle = sys::ZX_HANDLE_INVALID;
78 ok(sys::zx_interrupt_create(
79 sys::ZX_HANDLE_INVALID,
80 T::CREATE_FLAGS,
81 sys::ZX_INTERRUPT_VIRTUAL,
82 &mut handle,
83 ))?;
84 Handle::from_raw(handle)
85 };
86 Ok(Interrupt(handle, PhantomData))
87 }
88
89 pub fn trigger(&self, time: Instant<T>) -> Result<(), Status> {
93 let status = unsafe { sys::zx_interrupt_trigger(self.raw_handle(), 0, time.into_nanos()) };
95 ok(status)
96 }
97}
98
99impl<K: InterruptKind, T: Timeline> AsHandleRef for Interrupt<K, T> {
100 fn as_handle_ref(&self) -> HandleRef<'_> {
101 self.0.as_handle_ref()
102 }
103}
104
105impl<K: InterruptKind, T: Timeline> From<Handle> for Interrupt<K, T> {
106 fn from(handle: Handle) -> Self {
107 Interrupt::<K, T>(handle, PhantomData)
108 }
109}
110
111impl<K: InterruptKind, T: Timeline> From<Interrupt<K, T>> for Handle {
112 fn from(x: Interrupt<K, T>) -> Handle {
113 x.0
114 }
115}
116
117impl<K: InterruptKind> HandleBased for Interrupt<K> {}
118
119mod private {
120 pub trait Sealed {}
121}
122
123#[cfg(test)]
124mod tests {
125 use crate::{
126 BootInstant, Handle, Interrupt, MonotonicInstant, MonotonicTimeline, Port, PortOptions,
127 Status, VirtualInterrupt, VirtualInterruptKind,
128 };
129
130 #[test]
131 fn bind() {
132 let interrupt: Interrupt = Handle::invalid().into();
133 let port = Port::create_with_opts(PortOptions::BIND_TO_INTERRUPT);
134 let key = 1;
135 let result = interrupt.bind_port(&port, key);
136 assert_eq!(result.err(), Some(Status::BAD_HANDLE));
137 }
138
139 #[test]
140 fn ack() {
141 let interrupt: Interrupt = Handle::invalid().into();
142 let result = interrupt.ack();
143 assert_eq!(result.err(), Some(Status::BAD_HANDLE));
144 }
145
146 #[test]
147 fn trigger() {
148 let interrupt = VirtualInterrupt::create_virtual().unwrap();
149 let result = interrupt.trigger(BootInstant::from_nanos(10));
150 assert_eq!(result, Ok(()));
151 }
152
153 #[test]
154 fn trigger_monotimeline() {
155 let interrupt =
156 Interrupt::<VirtualInterruptKind, MonotonicTimeline>::create_virtual().unwrap();
157 let result = interrupt.trigger(MonotonicInstant::from_nanos(10));
158 assert_eq!(result, Ok(()));
159 }
160}