1#![forbid(unsafe_code)]
7
8pub mod bus;
9pub mod channel;
10pub mod gpadl;
11pub mod gpadl_ring;
12pub mod offer;
13pub mod resources;
14pub mod simple;
15pub mod stream;
16
17pub use stream::TaggedStream;
18
19use std::sync::Arc;
20use std::sync::atomic::AtomicBool;
21use std::sync::atomic::Ordering;
22use std::task::Context;
23use std::task::Poll;
24use vmbus_ring::FlatRingMem;
25use vmbus_ring::IncomingRing;
26use vmbus_ring::OutgoingRing;
27use vmbus_ring::RingMem;
28use vmcore::slim_event::SlimEvent;
29
30pub trait SignalVmbusChannel: Send + Sync {
36 fn signal_remote(&self);
41
42 fn poll_for_signal(&self, cx: &mut Context<'_>) -> Poll<Result<(), ChannelClosed>>;
47}
48
49pub struct ChannelClosed;
52
53pub fn connected_async_channels(
55 ring_size: usize,
56) -> (RawAsyncChannel<FlatRingMem>, RawAsyncChannel<FlatRingMem>) {
57 #[derive(Default)]
58 struct EventWithDoneInner {
59 event: SlimEvent,
60 done: AtomicBool,
61 }
62
63 struct SignalInProc {
64 local: Arc<EventWithDoneInner>,
65 remote: Arc<EventWithDoneInner>,
66 close_on_drop: bool,
67 }
68
69 impl SignalVmbusChannel for SignalInProc {
70 fn signal_remote(&self) {
71 self.remote.event.signal();
72 }
73
74 fn poll_for_signal(&self, cx: &mut Context<'_>) -> Poll<Result<(), ChannelClosed>> {
75 if self.local.done.load(Ordering::Relaxed) {
76 return Err(ChannelClosed).into();
77 }
78 self.local.event.poll_wait(cx).map(Ok)
79 }
80 }
81
82 impl Drop for SignalInProc {
83 fn drop(&mut self) {
84 if self.close_on_drop {
85 self.remote.done.store(true, Ordering::Relaxed);
86 self.remote.event.signal();
87 }
88 }
89 }
90
91 let host_notify = SignalInProc {
92 local: Default::default(),
93 remote: Default::default(),
94 close_on_drop: false,
95 };
96 let guest_notify = SignalInProc {
97 local: host_notify.remote.clone(),
98 remote: host_notify.local.clone(),
99 close_on_drop: true,
100 };
101 let (host_in_ring, guest_out_ring) = make_ring_pair(ring_size);
102 let (guest_in_ring, host_out_ring) = make_ring_pair(ring_size);
103
104 let host = RawAsyncChannel {
105 in_ring: host_in_ring,
106 out_ring: host_out_ring,
107 signal: Box::new(host_notify),
108 };
109 let guest = RawAsyncChannel {
110 in_ring: guest_in_ring,
111 out_ring: guest_out_ring,
112 signal: Box::new(guest_notify),
113 };
114 (host, guest)
115}
116
117fn make_ring_pair(size: usize) -> (IncomingRing<FlatRingMem>, OutgoingRing<FlatRingMem>) {
118 let flat_mem = FlatRingMem::new(size);
119 let ring1 = IncomingRing::new(flat_mem.clone()).unwrap();
120 let ring2 = OutgoingRing::new(flat_mem).unwrap();
121 (ring1, ring2)
122}
123
124pub struct RawAsyncChannel<M: RingMem> {
126 pub in_ring: IncomingRing<M>,
128 pub out_ring: OutgoingRing<M>,
130 pub signal: Box<dyn SignalVmbusChannel>,
132}