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;
15
16use std::sync::Arc;
17use std::sync::atomic::AtomicBool;
18use std::sync::atomic::Ordering;
19use std::task::Context;
20use std::task::Poll;
21use vmbus_ring::FlatRingMem;
22use vmbus_ring::IncomingRing;
23use vmbus_ring::OutgoingRing;
24use vmbus_ring::RingMem;
25use vmcore::slim_event::SlimEvent;
26
27pub trait SignalVmbusChannel: Send + Sync {
33 fn signal_remote(&self);
38
39 fn poll_for_signal(&self, cx: &mut Context<'_>) -> Poll<Result<(), ChannelClosed>>;
44}
45
46pub struct ChannelClosed;
49
50pub fn connected_async_channels(
52 ring_size: usize,
53) -> (RawAsyncChannel<FlatRingMem>, RawAsyncChannel<FlatRingMem>) {
54 #[derive(Default)]
55 struct EventWithDoneInner {
56 event: SlimEvent,
57 done: AtomicBool,
58 }
59
60 struct SignalInProc {
61 local: Arc<EventWithDoneInner>,
62 remote: Arc<EventWithDoneInner>,
63 close_on_drop: bool,
64 }
65
66 impl SignalVmbusChannel for SignalInProc {
67 fn signal_remote(&self) {
68 self.remote.event.signal();
69 }
70
71 fn poll_for_signal(&self, cx: &mut Context<'_>) -> Poll<Result<(), ChannelClosed>> {
72 if self.local.done.load(Ordering::Relaxed) {
73 return Err(ChannelClosed).into();
74 }
75 self.local.event.poll_wait(cx).map(Ok)
76 }
77 }
78
79 impl Drop for SignalInProc {
80 fn drop(&mut self) {
81 if self.close_on_drop {
82 self.remote.done.store(true, Ordering::Relaxed);
83 self.remote.event.signal();
84 }
85 }
86 }
87
88 let host_notify = SignalInProc {
89 local: Default::default(),
90 remote: Default::default(),
91 close_on_drop: false,
92 };
93 let guest_notify = SignalInProc {
94 local: host_notify.remote.clone(),
95 remote: host_notify.local.clone(),
96 close_on_drop: true,
97 };
98 let (host_in_ring, guest_out_ring) = make_ring_pair(ring_size);
99 let (guest_in_ring, host_out_ring) = make_ring_pair(ring_size);
100
101 let host = RawAsyncChannel {
102 in_ring: host_in_ring,
103 out_ring: host_out_ring,
104 signal: Box::new(host_notify),
105 };
106 let guest = RawAsyncChannel {
107 in_ring: guest_in_ring,
108 out_ring: guest_out_ring,
109 signal: Box::new(guest_notify),
110 };
111 (host, guest)
112}
113
114fn make_ring_pair(size: usize) -> (IncomingRing<FlatRingMem>, OutgoingRing<FlatRingMem>) {
115 let flat_mem = FlatRingMem::new(size);
116 let ring1 = IncomingRing::new(flat_mem.clone()).unwrap();
117 let ring2 = OutgoingRing::new(flat_mem).unwrap();
118 (ring1, ring2)
119}
120
121pub struct RawAsyncChannel<M: RingMem> {
123 pub in_ring: IncomingRing<M>,
125 pub out_ring: OutgoingRing<M>,
127 pub signal: Box<dyn SignalVmbusChannel>,
129}