#![forbid(unsafe_code)]
pub mod bus;
pub mod channel;
pub mod gpadl;
pub mod gpadl_ring;
pub mod offer;
pub mod resources;
pub mod simple;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::task::Context;
use std::task::Poll;
use vmbus_ring::FlatRingMem;
use vmbus_ring::IncomingRing;
use vmbus_ring::OutgoingRing;
use vmbus_ring::RingMem;
use vmcore::slim_event::SlimEvent;
pub trait SignalVmbusChannel: Send + Sync {
fn signal_remote(&self);
fn poll_for_signal(&self, cx: &mut Context<'_>) -> Poll<Result<(), ChannelClosed>>;
}
pub struct ChannelClosed;
pub fn connected_async_channels(
ring_size: usize,
) -> (RawAsyncChannel<FlatRingMem>, RawAsyncChannel<FlatRingMem>) {
#[derive(Default)]
struct EventWithDoneInner {
event: SlimEvent,
done: AtomicBool,
}
struct SignalInProc {
local: Arc<EventWithDoneInner>,
remote: Arc<EventWithDoneInner>,
close_on_drop: bool,
}
impl SignalVmbusChannel for SignalInProc {
fn signal_remote(&self) {
self.remote.event.signal();
}
fn poll_for_signal(&self, cx: &mut Context<'_>) -> Poll<Result<(), ChannelClosed>> {
if self.local.done.load(Ordering::Relaxed) {
return Err(ChannelClosed).into();
}
self.local.event.poll_wait(cx).map(Ok)
}
}
impl Drop for SignalInProc {
fn drop(&mut self) {
if self.close_on_drop {
self.remote.done.store(true, Ordering::Relaxed);
self.remote.event.signal();
}
}
}
let host_notify = SignalInProc {
local: Default::default(),
remote: Default::default(),
close_on_drop: false,
};
let guest_notify = SignalInProc {
local: host_notify.remote.clone(),
remote: host_notify.local.clone(),
close_on_drop: true,
};
let (host_in_ring, guest_out_ring) = make_ring_pair(ring_size);
let (guest_in_ring, host_out_ring) = make_ring_pair(ring_size);
let host = RawAsyncChannel {
in_ring: host_in_ring,
out_ring: host_out_ring,
signal: Box::new(host_notify),
};
let guest = RawAsyncChannel {
in_ring: guest_in_ring,
out_ring: guest_out_ring,
signal: Box::new(guest_notify),
};
(host, guest)
}
fn make_ring_pair(size: usize) -> (IncomingRing<FlatRingMem>, OutgoingRing<FlatRingMem>) {
let flat_mem = FlatRingMem::new(size);
let ring1 = IncomingRing::new(flat_mem.clone()).unwrap();
let ring2 = OutgoingRing::new(flat_mem).unwrap();
(ring1, ring2)
}
pub struct RawAsyncChannel<M: RingMem> {
pub in_ring: IncomingRing<M>,
pub out_ring: OutgoingRing<M>,
pub signal: Box<dyn SignalVmbusChannel>,
}