1use std::ffi::c_void;
2
3use xen_sys::vm_event_back_ring;
4
5use crate::{
6 RING_GET_REQUEST, RING_HAS_UNCONSUMED_REQUESTS, RING_PUSH_RESPONSES, RING_PUT_RESPONSE,
7 consts::PAGE_SIZE, ctrl::VmEvent,
8};
9
10pub struct VmEventRing {
11 ring_page: *mut c_void,
12 back_ring: vm_event_back_ring,
13}
14
15impl VmEventRing {
16 pub(crate) fn new(ring_page: *mut c_void, back_ring: vm_event_back_ring) -> Self {
17 Self {
18 ring_page,
19 back_ring,
20 }
21 }
22
23 pub fn unconsumed_requests(&self) -> usize {
24 RING_HAS_UNCONSUMED_REQUESTS!(self.back_ring) as usize
25 }
26
27 pub fn has_unconsumed_requests(&self) -> bool {
28 self.unconsumed_requests() != 0
29 }
30
31 pub fn get_request(&mut self) -> VmEvent {
32 let mut req_cons = self.back_ring.req_cons;
33
34 let req = RING_GET_REQUEST!(self.back_ring, req_cons);
36 req_cons += 1;
37
38 self.back_ring.req_cons = req_cons;
40 unsafe {
41 (*(self.back_ring.sring)).req_event = req_cons + 1;
42 }
43 req.into()
44 }
45
46 pub fn put_response(&mut self, rsp: VmEvent) {
47 let mut rsp_prod = self.back_ring.rsp_prod_pvt;
48
49 RING_PUT_RESPONSE!(self.back_ring, rsp_prod, rsp.into());
51 rsp_prod += 1;
52
53 self.back_ring.rsp_prod_pvt = rsp_prod;
55 RING_PUSH_RESPONSES!(self.back_ring);
56 }
57}
58
59impl Drop for VmEventRing {
60 fn drop(&mut self) {
61 tracing::trace!("unmapping ring page");
62 unsafe {
63 libc::munmap(self.ring_page, PAGE_SIZE as usize);
64 }
65 }
66}