shadow_rs/utility/
legacy_callback_queue.rs1use std::cell::RefCell;
2use std::ops::DerefMut;
3
4use shadow_shim_helper_rs::rootedcell::refcell::RootedRefCell;
5
6use crate::host::descriptor::FileState;
7use crate::host::descriptor::listener::StateEventSource;
8use crate::utility::callback_queue::CallbackQueue;
9
10#[allow(non_camel_case_types)]
12pub type RootedRefCell_StateEventSource = RootedRefCell<StateEventSource>;
13
14thread_local! {
15    static C_CALLBACK_QUEUE: RefCell<Option<CallbackQueue>> = const { RefCell::new(None) };
16}
17
18pub fn with_global_cb_queue<T>(f: impl FnOnce() -> T) -> T {
27    C_CALLBACK_QUEUE.with(|cb_queue| {
28        if cb_queue.borrow().is_some() {
29            return f();
32        }
33
34        assert!(
36            cb_queue
37                .borrow_mut()
38                .replace(CallbackQueue::new())
39                .is_none()
40        );
41
42        let rv = f();
43
44        loop {
46            let mut queue_to_run = cb_queue.borrow_mut().replace(CallbackQueue::new()).unwrap();
49            if queue_to_run.is_empty() {
50                break;
52            }
53            queue_to_run.run();
54        }
55
56        assert!(cb_queue.borrow_mut().take().is_some());
57
58        rv
59    })
60}
61mod export {
62    use super::*;
63
64    use std::net::Ipv4Addr;
65
66    use crate::core::worker;
67    use crate::host::descriptor::FileSignals;
68    use crate::host::descriptor::socket::inet::InetSocket;
69    use crate::host::host::Host;
70
71    #[unsafe(no_mangle)]
74    pub unsafe extern "C-unwind" fn notify_listeners_with_global_cb_queue(
75        event_source: *const RootedRefCell_StateEventSource,
76        state: FileState,
77        changed: FileState,
78        signals: FileSignals,
79    ) {
80        let event_source = unsafe { event_source.as_ref() }.unwrap();
81
82        with_global_cb_queue(|| {
83            C_CALLBACK_QUEUE.with(|cb_queue| {
84                let mut cb_queue = cb_queue.borrow_mut();
85                let cb_queue = cb_queue.deref_mut().as_mut().unwrap();
87
88                worker::Worker::with_active_host(|host| {
89                    let mut event_source = event_source.borrow_mut(host.root());
90                    event_source.notify_listeners(state, changed, signals, cb_queue)
91                })
92                .unwrap();
93            });
94        });
95    }
96
97    #[unsafe(no_mangle)]
101    pub unsafe extern "C-unwind" fn socket_wants_to_send_with_global_cb_queue(
102        host: *const Host,
103        socket: *mut InetSocket,
104        ip: libc::in_addr_t,
105    ) {
106        let host = unsafe { host.as_ref() }.unwrap();
107        let ip = Ipv4Addr::from(u32::from_be(ip));
108
109        let host_id = host.id();
110
111        with_global_cb_queue(|| {
112            C_CALLBACK_QUEUE.with(|cb_queue| {
113                let mut cb_queue = cb_queue.borrow_mut();
114                let cb_queue = cb_queue.deref_mut().as_mut().unwrap();
116
117                cb_queue.add(move |_cb_queue| {
118                    worker::Worker::with_active_host(|host| {
119                        assert_eq!(host.id(), host_id);
120                        let socket = unsafe { Box::from_raw(socket) };
121                        host.notify_socket_has_packets(ip, &socket);
122                    })
123                    .unwrap();
124                });
125            });
126        });
127    }
128}