1use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
4use std::collections::BTreeMap;
5use std::ffi::{CStr, CString, OsString};
6use std::net::{Ipv4Addr, SocketAddrV4};
7use std::ops::{Deref, DerefMut};
8use std::os::unix::prelude::OsStringExt;
9use std::path::{Path, PathBuf};
10use std::sync::{Arc, Mutex};
11
12use asm_util::tsc::Tsc;
13use atomic_refcell::AtomicRefCell;
14use linux_api::signal::{Signal, siginfo_t};
15use log::{debug, trace};
16use logger::LogLevel;
17use once_cell::unsync::OnceCell;
18use rand::SeedableRng;
19use rand_xoshiro::Xoshiro256PlusPlus;
20use shadow_shim_helper_rs::HostId;
21use shadow_shim_helper_rs::emulated_time::EmulatedTime;
22use shadow_shim_helper_rs::explicit_drop::ExplicitDropper;
23use shadow_shim_helper_rs::rootedcell::Root;
24use shadow_shim_helper_rs::rootedcell::cell::RootedCell;
25use shadow_shim_helper_rs::rootedcell::rc::RootedRc;
26use shadow_shim_helper_rs::rootedcell::refcell::RootedRefCell;
27use shadow_shim_helper_rs::shim_shmem::{HostShmem, HostShmemProtected, ManagerShmem};
28use shadow_shim_helper_rs::simulation_time::SimulationTime;
29use shadow_shmem::allocator::ShMemBlock;
30use vasi_sync::scmutex::SelfContainedMutexGuard;
31
32use crate::core::configuration::{ProcessFinalState, QDiscMode};
33use crate::core::sim_config::PcapConfig;
34use crate::core::work::event::{Event, EventData};
35use crate::core::work::event_queue::EventQueue;
36use crate::core::work::task::TaskRef;
37use crate::core::worker::Worker;
38use crate::cshadow;
39use crate::host::descriptor::socket::abstract_unix_ns::AbstractUnixNamespace;
40use crate::host::descriptor::socket::inet::InetSocket;
41use crate::host::futex_table::FutexTable;
42use crate::host::network::interface::{FifoPacketPriority, NetworkInterface, PcapOptions};
43use crate::host::network::namespace::NetworkNamespace;
44use crate::host::process::Process;
45use crate::host::thread::{Thread, ThreadId};
46use crate::network::PacketDevice;
47use crate::network::relay::{RateLimit, Relay};
48use crate::network::router::Router;
49use crate::utility;
50#[cfg(feature = "perf_timers")]
51use crate::utility::perf_timer::PerfTimer;
52
53pub struct HostParameters {
54    pub id: HostId,
55    pub node_seed: u64,
56    pub hostname: CString,
59    pub node_id: u32,
60    pub ip_addr: libc::in_addr_t,
61    pub sim_end_time: EmulatedTime,
62    pub requested_bw_down_bits: u64,
63    pub requested_bw_up_bits: u64,
64    pub cpu_frequency: u64,
65    pub cpu_threshold: Option<SimulationTime>,
66    pub cpu_precision: Option<SimulationTime>,
67    pub log_level: LogLevel,
68    pub pcap_config: Option<PcapConfig>,
69    pub qdisc: QDiscMode,
70    pub init_sock_recv_buf_size: u64,
71    pub autotune_recv_buf: bool,
72    pub init_sock_send_buf_size: u64,
73    pub autotune_send_buf: bool,
74    pub native_tsc_frequency: u64,
75    pub model_unblocked_syscall_latency: bool,
76    pub max_unapplied_cpu_latency: SimulationTime,
77    pub unblocked_syscall_latency: SimulationTime,
78    pub unblocked_vdso_latency: SimulationTime,
79    pub strace_logging_options: Option<FmtOptions>,
80    pub shim_log_level: LogLevel,
81    pub use_new_tcp: bool,
82    pub use_mem_mapper: bool,
83    pub use_syscall_counters: bool,
84}
85
86use super::cpu::Cpu;
87use super::process::ProcessId;
88use super::syscall::formatter::FmtOptions;
89
90#[derive(Debug, Clone)]
92pub struct HostInfo {
93    pub id: HostId,
94    pub name: String,
95    pub default_ip: Ipv4Addr,
96    pub log_level: Option<log::LevelFilter>,
97}
98
99pub struct Host {
101    info: OnceCell<Arc<HostInfo>>,
108
109    root: Root,
114
115    event_queue: Arc<Mutex<EventQueue>>,
116
117    random: RefCell<Xoshiro256PlusPlus>,
118
119    router: RefCell<Router>,
123
124    relay_inet_out: Arc<Relay>,
126    relay_inet_in: Arc<Relay>,
128    relay_loopback: Arc<Relay>,
130
131    futex_table: RefCell<FutexTable>,
133
134    #[cfg(feature = "perf_timers")]
135    execution_timer: RefCell<PerfTimer>,
136
137    pub params: HostParameters,
138
139    cpu: RefCell<Cpu>,
140
141    net_ns: NetworkNamespace,
142
143    data_dir_path: PathBuf,
149    data_dir_path_cstring: CString,
150
151    thread_id_counter: Cell<libc::pid_t>,
153    event_id_counter: Cell<u64>,
154    packet_id_counter: Cell<u64>,
155
156    determinism_sequence_counter: Cell<u64>,
158
159    packet_priority_counter: Cell<FifoPacketPriority>,
161
162    processes: RefCell<BTreeMap<ProcessId, RootedRc<RootedRefCell<Process>>>>,
164
165    tsc: Tsc,
166    shim_shmem_lock:
177        RefCell<Option<UnsafeCell<SelfContainedMutexGuard<'static, HostShmemProtected>>>>,
178    shim_shmem: UnsafeCell<ShMemBlock<'static, HostShmem>>,
190
191    in_notify_socket_has_packets: RootedCell<bool>,
192
193    preload_paths: Arc<Vec<PathBuf>>,
195}
196
197impl crate::utility::IsSend for Host {}
199
200impl std::fmt::Debug for Host {
202    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203        f.debug_struct("Host")
204            .field("info", &self.info)
205            .finish_non_exhaustive()
206    }
207}
208
209impl Host {
210    pub fn new(
211        params: HostParameters,
212        host_root_path: &Path,
213        raw_cpu_freq_khz: u64,
214        manager_shmem: &ShMemBlock<ManagerShmem>,
215        preload_paths: Arc<Vec<PathBuf>>,
216    ) -> Self {
217        #[cfg(feature = "perf_timers")]
218        let execution_timer = RefCell::new(PerfTimer::new_started());
219
220        let root = Root::new();
221        let random = RefCell::new(Xoshiro256PlusPlus::seed_from_u64(params.node_seed));
222        let cpu = RefCell::new(Cpu::new(
223            params.cpu_frequency,
224            raw_cpu_freq_khz,
225            params.cpu_threshold,
226            params.cpu_precision,
227        ));
228        let data_dir_path = Self::make_data_dir_path(¶ms.hostname, host_root_path);
229        let data_dir_path_cstring = utility::pathbuf_to_nul_term_cstring(data_dir_path.clone());
230
231        let host_shmem = HostShmem::new(
232            params.id,
233            params.model_unblocked_syscall_latency,
234            params.max_unapplied_cpu_latency,
235            params.unblocked_syscall_latency,
236            params.unblocked_vdso_latency,
237            nix::unistd::getpid().as_raw(),
238            params.native_tsc_frequency,
239            params.shim_log_level,
240            manager_shmem,
241        );
242        let shim_shmem = UnsafeCell::new(shadow_shmem::allocator::shmalloc(host_shmem));
243
244        let thread_id_counter = Cell::new(1000);
246        let event_id_counter = Cell::new(0);
247        let packet_id_counter = Cell::new(0);
248        let determinism_sequence_counter = Cell::new(0);
249        let packet_priority_counter = Cell::new(1);
251        let tsc = Tsc::new(params.native_tsc_frequency);
252
253        std::fs::create_dir_all(&data_dir_path).unwrap();
254
255        let public_ip: Ipv4Addr = u32::from_be(params.ip_addr).into();
259
260        let pcap_options = params.pcap_config.as_ref().map(|x| PcapOptions {
261            path: data_dir_path.clone(),
262            capture_size_bytes: x.capture_size.try_into().unwrap(),
263        });
264
265        let net_ns = NetworkNamespace::new(public_ip, pcap_options, params.qdisc);
266
267        let router = Router::new(Ipv4Addr::UNSPECIFIED);
271        let relay_inet_out = Relay::new(
272            RateLimit::BytesPerSecond(params.requested_bw_up_bits / 8),
273            net_ns.internet.borrow().get_address(),
274        );
275        let relay_inet_in = Relay::new(
276            RateLimit::BytesPerSecond(params.requested_bw_down_bits / 8),
277            router.get_address(),
278        );
279        let relay_loopback = Relay::new(
280            RateLimit::Unlimited,
281            net_ns.localhost.borrow().get_address(),
282        );
283
284        let in_notify_socket_has_packets = RootedCell::new(&root, false);
285
286        let res = Self {
287            info: OnceCell::new(),
288            root,
289            event_queue: Arc::new(Mutex::new(EventQueue::new())),
290            params,
291            router: RefCell::new(router),
292            relay_inet_out: Arc::new(relay_inet_out),
293            relay_inet_in: Arc::new(relay_inet_in),
294            relay_loopback: Arc::new(relay_loopback),
295            futex_table: RefCell::new(FutexTable::new()),
296            random,
297            shim_shmem,
298            shim_shmem_lock: RefCell::new(None),
299            cpu,
300            net_ns,
301            data_dir_path,
302            data_dir_path_cstring,
303            thread_id_counter,
304            event_id_counter,
305            packet_id_counter,
306            packet_priority_counter,
307            determinism_sequence_counter,
308            tsc,
309            processes: RefCell::new(BTreeMap::new()),
310            #[cfg(feature = "perf_timers")]
311            execution_timer,
312            in_notify_socket_has_packets,
313            preload_paths,
314        };
315
316        res.stop_execution_timer();
317
318        debug!(
319            concat!(
320                "Setup host id '{:?}'",
321                " name '{name}'",
322                " with seed {seed},",
323                " {bw_up_kiBps} bwUpKiBps,",
324                " {bw_down_kiBps} bwDownKiBps,",
325                " {init_sock_send_buf_size} initSockSendBufSize,",
326                " {init_sock_recv_buf_size} initSockRecvBufSize, ",
327                " {cpu_frequency:?} cpuFrequency, ",
328                " {cpu_threshold:?} cpuThreshold, ",
329                " {cpu_precision:?} cpuPrecision"
330            ),
331            res.id(),
332            name = res.info().name,
333            seed = res.params.node_seed,
334            bw_up_kiBps = res.bw_up_kiBps(),
335            bw_down_kiBps = res.bw_down_kiBps(),
336            init_sock_send_buf_size = res.params.init_sock_send_buf_size,
337            init_sock_recv_buf_size = res.params.init_sock_recv_buf_size,
338            cpu_frequency = res.params.cpu_frequency,
339            cpu_threshold = res.params.cpu_threshold,
340            cpu_precision = res.params.cpu_precision,
341        );
342
343        res
344    }
345
346    pub fn root(&self) -> &Root {
347        &self.root
348    }
349
350    fn make_data_dir_path(hostname: &CStr, host_root_path: &Path) -> PathBuf {
351        let hostname: OsString = { OsString::from_vec(hostname.to_bytes().to_vec()) };
352
353        let mut data_dir_path = PathBuf::new();
354        data_dir_path.push(host_root_path);
355        data_dir_path.push(&hostname);
356        data_dir_path
357    }
358
359    pub fn data_dir_path(&self) -> &Path {
360        &self.data_dir_path
361    }
362
363    pub fn add_application(
364        &self,
365        start_time: SimulationTime,
366        shutdown_time: Option<SimulationTime>,
367        shutdown_signal: nix::sys::signal::Signal,
368        plugin_name: CString,
369        plugin_path: CString,
370        argv: Vec<CString>,
371        envv: Vec<CString>,
372        pause_for_debugging: bool,
373        expected_final_state: ProcessFinalState,
374    ) {
375        debug_assert!(shutdown_time.is_none() || shutdown_time.unwrap() > start_time);
376
377        let task = TaskRef::new(move |host| {
379            let envv = envv.clone();
383            let argv = argv.clone();
384
385            let process = Process::spawn(
386                host,
387                plugin_name.clone(),
388                &plugin_path,
389                argv,
390                envv,
391                pause_for_debugging,
392                host.params.strace_logging_options,
393                expected_final_state,
394            )
395            .unwrap_or_else(|e| panic!("Failed to initialize application {plugin_name:?}: {e:?}"));
396            let (process_id, thread_id) = {
397                let process = process.borrow(host.root());
398                (process.id(), process.thread_group_leader_id())
399            };
400            host.processes.borrow_mut().insert(process_id, process);
401
402            if let Some(shutdown_time) = shutdown_time {
403                let task = TaskRef::new(move |host| {
404                    let Some(process) = host.process_borrow(process_id) else {
405                        debug!(
406                            "Can't send shutdown signal to process {process_id}; it no longer exists"
407                        );
408                        return;
409                    };
410                    let process = process.borrow(host.root());
411                    let siginfo_t = siginfo_t::new_for_kill(
412                        Signal::try_from(shutdown_signal as i32).unwrap(),
413                        1,
414                        0,
415                    );
416                    process.signal(host, None, &siginfo_t);
417                });
418                host.schedule_task_at_emulated_time(
419                    task,
420                    EmulatedTime::SIMULATION_START + shutdown_time,
421                );
422            }
423
424            host.resume(process_id, thread_id);
425        });
426        self.schedule_task_at_emulated_time(task, EmulatedTime::SIMULATION_START + start_time);
427    }
428
429    pub fn add_and_schedule_forked_process(
430        &self,
431        host: &Host,
432        process: RootedRc<RootedRefCell<Process>>,
433    ) {
434        let (process_id, thread_id) = {
435            let process = process.borrow(&self.root);
436            (process.id(), process.thread_group_leader_id())
437        };
438        host.processes.borrow_mut().insert(process_id, process);
439        let task = TaskRef::new(move |host| {
441            host.resume(process_id, thread_id);
442        });
443        self.schedule_task_with_delay(task, SimulationTime::ZERO);
444    }
445
446    pub fn resume(&self, pid: ProcessId, tid: ThreadId) {
447        let Some(processrc) = self
448            .process_borrow(pid)
449            .map(|p| RootedRc::clone(&p, &self.root))
450        else {
451            trace!("{pid:?} doesn't exist");
452            return;
453        };
454        let processrc = ExplicitDropper::new(processrc, |p| {
455            p.explicit_drop_recursive(&self.root, self);
456        });
457        let died;
458        let is_orphan;
459        {
460            Worker::set_active_process(&processrc);
461            let process = processrc.borrow(self.root());
462            process.resume(self, tid);
463            Worker::clear_active_process();
464            let zombie_state = process.borrow_as_zombie();
465            if let Some(zombie) = zombie_state {
466                died = true;
467                is_orphan = zombie.reaper(self).is_none();
468            } else {
469                died = false;
470                is_orphan = false;
471            }
472        };
473
474        if !died {
475            return;
476        }
477
478        let mut orphaned_zombie_pids: Vec<ProcessId> = self
480            .processes
481            .borrow()
482            .iter()
483            .filter_map(|(other_pid, processrc)| {
484                let process = processrc.borrow(&self.root);
485                if process.parent_id() != pid {
486                    return None;
488                }
489                process.set_parent_id(ProcessId::INIT);
490                let Some(z) = process.borrow_as_zombie() else {
491                    return None;
493                };
494                if z.reaper(self).is_some() {
495                    None
497                } else {
498                    Some(*other_pid)
500                }
501            })
502            .collect();
503
504        debug_assert!(died);
506        if is_orphan {
507            orphaned_zombie_pids.push(pid);
508        }
509
510        let mut processes = self.processes.borrow_mut();
512        for pid in orphaned_zombie_pids {
513            trace!("Dropping orphan zombie process {pid:?}");
514            let processrc = processes.remove(&pid).unwrap();
515            RootedRc::explicit_drop_recursive(processrc, &self.root, self);
516        }
517    }
518
519    #[track_caller]
520    pub fn process_borrow(
521        &self,
522        id: ProcessId,
523    ) -> Option<impl Deref<Target = RootedRc<RootedRefCell<Process>>> + '_> {
524        Ref::filter_map(self.processes.borrow(), |processes| processes.get(&id)).ok()
525    }
526
527    #[track_caller]
529    pub fn process_remove(&self, id: ProcessId) -> Option<RootedRc<RootedRefCell<Process>>> {
530        self.processes.borrow_mut().remove(&id)
531    }
532
533    #[track_caller]
542    pub fn processes_borrow(
543        &self,
544    ) -> impl Deref<Target = BTreeMap<ProcessId, RootedRc<RootedRefCell<Process>>>> + '_ {
545        self.processes.borrow()
546    }
547
548    pub fn cpu_borrow(&self) -> impl Deref<Target = Cpu> + '_ {
549        self.cpu.borrow()
550    }
551
552    pub fn cpu_borrow_mut(&self) -> impl DerefMut<Target = Cpu> + '_ {
553        self.cpu.borrow_mut()
554    }
555
556    pub fn info(&self) -> &Arc<HostInfo> {
561        self.info.get_or_init(|| {
562            Arc::new(HostInfo {
563                id: self.id(),
564                name: self.params.hostname.to_str().unwrap().to_owned(),
565                default_ip: self.default_ip(),
566                log_level: self.log_level(),
567            })
568        })
569    }
570
571    pub fn id(&self) -> HostId {
572        self.params.id
573    }
574
575    pub fn name(&self) -> &str {
576        &self.info().name
577    }
578
579    pub fn default_ip(&self) -> Ipv4Addr {
580        self.net_ns.default_ip
581    }
582
583    pub fn abstract_unix_namespace(
584        &self,
585    ) -> impl Deref<Target = Arc<AtomicRefCell<AbstractUnixNamespace>>> + '_ {
586        &self.net_ns.unix
587    }
588
589    pub fn log_level(&self) -> Option<log::LevelFilter> {
590        let level = self.params.log_level;
591        log_c2rust::c_to_rust_log_level(level).map(|l| l.to_level_filter())
592    }
593
594    #[track_caller]
595    pub fn upstream_router_borrow_mut(&self) -> impl DerefMut<Target = Router> + '_ {
596        self.router.borrow_mut()
597    }
598
599    #[track_caller]
600    pub fn network_namespace_borrow(&self) -> impl Deref<Target = NetworkNamespace> + '_ {
601        &self.net_ns
602    }
603
604    #[track_caller]
605    pub fn futextable_borrow(&self) -> impl Deref<Target = FutexTable> + '_ {
606        self.futex_table.borrow()
607    }
608
609    #[track_caller]
610    pub fn futextable_borrow_mut(&self) -> impl DerefMut<Target = FutexTable> + '_ {
611        self.futex_table.borrow_mut()
612    }
613
614    #[allow(non_snake_case)]
615    pub fn bw_up_kiBps(&self) -> u64 {
616        self.params.requested_bw_up_bits / (8 * 1024)
617    }
618
619    #[allow(non_snake_case)]
620    pub fn bw_down_kiBps(&self) -> u64 {
621        self.params.requested_bw_down_bits / (8 * 1024)
622    }
623
624    pub fn interface_borrow_mut(
628        &self,
629        addr: Ipv4Addr,
630    ) -> Option<impl DerefMut<Target = NetworkInterface> + '_> {
631        self.net_ns.interface_borrow_mut(addr)
632    }
633
634    pub fn interface_borrow(
638        &self,
639        addr: Ipv4Addr,
640    ) -> Option<impl Deref<Target = NetworkInterface> + '_> {
641        self.net_ns.interface_borrow(addr)
642    }
643
644    #[track_caller]
645    pub fn random_mut(&self) -> impl DerefMut<Target = Xoshiro256PlusPlus> + '_ {
646        self.random.borrow_mut()
647    }
648
649    pub fn get_new_event_id(&self) -> u64 {
650        let res = self.event_id_counter.get();
651        self.event_id_counter.set(res + 1);
652        res
653    }
654
655    pub fn get_new_thread_id(&self) -> ThreadId {
656        let res = self.thread_id_counter.get();
657        self.thread_id_counter.set(res + 1);
658        res.try_into().unwrap()
659    }
660
661    pub fn get_new_packet_id(&self) -> u64 {
662        let res = self.packet_id_counter.get();
663        self.packet_id_counter.set(res + 1);
664        res
665    }
666
667    pub fn get_next_deterministic_sequence_value(&self) -> u64 {
668        let res = self.determinism_sequence_counter.get();
669        self.determinism_sequence_counter.set(res + 1);
670        res
671    }
672
673    pub fn get_next_packet_priority(&self) -> FifoPacketPriority {
674        let res = self.packet_priority_counter.get();
675        self.packet_priority_counter
676            .set(res.checked_add(1).unwrap());
677        res
678    }
679
680    pub fn continue_execution_timer(&self) {
681        #[cfg(feature = "perf_timers")]
682        self.execution_timer.borrow_mut().start();
683    }
684
685    pub fn stop_execution_timer(&self) {
686        #[cfg(feature = "perf_timers")]
687        self.execution_timer.borrow_mut().stop();
688    }
689
690    pub fn schedule_task_at_emulated_time(&self, task: TaskRef, t: EmulatedTime) -> bool {
691        let event = Event::new_local(task, t, self);
692        self.push_local_event(event)
693    }
694
695    pub fn schedule_task_with_delay(&self, task: TaskRef, t: SimulationTime) -> bool {
696        self.schedule_task_at_emulated_time(task, Worker::current_time().unwrap() + t)
697    }
698
699    pub fn event_queue(&self) -> &Arc<Mutex<EventQueue>> {
700        &self.event_queue
701    }
702
703    pub fn push_local_event(&self, event: Event) -> bool {
704        if event.time() >= self.params.sim_end_time {
705            return false;
706        }
707        self.event_queue.lock().unwrap().push(event);
708        true
709    }
710
711    pub fn shutdown(&self) {
713        self.continue_execution_timer();
714
715        debug!("shutting down host {}", self.name());
716
717        self.net_ns.cleanup();
719
720        assert!(self.processes.borrow().is_empty());
721
722        self.stop_execution_timer();
723        #[cfg(feature = "perf_timers")]
724        debug!(
725            "host '{}' has been shut down, total execution time was {:?}",
726            self.name(),
727            self.execution_timer.borrow().elapsed()
728        );
729    }
730
731    pub fn free_all_applications(&self) {
732        trace!("start freeing applications for host '{}'", self.name());
733        let processes = std::mem::take(&mut *self.processes.borrow_mut());
734        for (_id, processrc) in processes.into_iter() {
735            let processrc = ExplicitDropper::new(processrc, |p| {
736                p.explicit_drop_recursive(self.root(), self);
737            });
738            Worker::set_active_process(&processrc);
739            let process = processrc.borrow(self.root());
740            process.stop(self);
741            Worker::clear_active_process();
742            process.set_parent_id(ProcessId::INIT);
745        }
746        trace!("done freeing application for host '{}'", self.name());
747    }
748
749    pub fn execute(&self, until: EmulatedTime) {
750        loop {
751            let mut event = {
752                let mut event_queue = self.event_queue.lock().unwrap();
753                match event_queue.next_event_time() {
754                    Some(t) if t < until => {}
755                    _ => break,
756                };
757                event_queue.pop().unwrap()
758            };
759
760            {
761                let mut cpu = self.cpu.borrow_mut();
762                cpu.update_time(event.time());
763                let cpu_delay = cpu.delay();
764                if cpu_delay > SimulationTime::ZERO {
765                    trace!("event blocked on CPU, rescheduled for {cpu_delay:?} from now");
766
767                    event.set_time(event.time() + cpu_delay);
769                    self.push_local_event(event);
770
771                    continue;
773                }
774            }
775
776            Worker::set_current_time(event.time());
778            self.continue_execution_timer();
779            match event.data() {
780                EventData::Packet(data) => {
781                    self.upstream_router_borrow_mut()
782                        .route_incoming_packet(data.into());
783                    self.notify_router_has_packets();
784                }
785                EventData::Local(data) => TaskRef::from(data).execute(self),
786            }
787            self.stop_execution_timer();
788            Worker::clear_current_time();
789        }
790    }
791
792    pub fn next_event_time(&self) -> Option<EmulatedTime> {
793        self.event_queue.lock().unwrap().next_event_time()
794    }
795
796    pub fn shim_shmem(&self) -> &ShMemBlock<'static, HostShmem> {
802        unsafe { &*self.shim_shmem.get() }
803    }
804
805    pub fn thread_cloned_rc(
808        &self,
809        virtual_tid: ThreadId,
810    ) -> Option<RootedRc<RootedRefCell<Thread>>> {
811        for process in self.processes.borrow().values() {
812            let process = process.borrow(self.root());
813            if let Some(thread) = process.thread_borrow(virtual_tid) {
814                return Some(RootedRc::clone(&*thread, self.root()));
815            };
816        }
817
818        None
819    }
820
821    pub fn has_thread(&self, virtual_tid: ThreadId) -> bool {
823        for process in self.processes.borrow().values() {
824            let process = process.borrow(self.root());
825            if process.thread_borrow(virtual_tid).is_some() {
826                return true;
827            }
828        }
829
830        false
831    }
832
833    pub fn lock_shmem(&self) {
839        let shim_shmem: &'static ShMemBlock<HostShmem> =
851            unsafe { self.shim_shmem.get().as_ref().unwrap() };
852        let lock = shim_shmem.protected().lock();
853        let prev = self
854            .shim_shmem_lock
855            .borrow_mut()
856            .replace(UnsafeCell::new(lock));
857        assert!(prev.is_none());
858    }
859
860    pub fn unlock_shmem(&self) {
863        let prev = self.shim_shmem_lock.borrow_mut().take();
864        assert!(prev.is_some());
865    }
866
867    pub fn shim_shmem_lock_borrow(&self) -> Option<impl Deref<Target = HostShmemProtected> + '_> {
868        Ref::filter_map(self.shim_shmem_lock.borrow(), |l| {
869            l.as_ref().map(|l| {
870                let guard = unsafe { &*l.get() };
874                guard.deref()
875            })
876        })
877        .ok()
878    }
879
880    pub fn shim_shmem_lock_borrow_mut(
881        &self,
882    ) -> Option<impl DerefMut<Target = HostShmemProtected> + '_> {
883        RefMut::filter_map(self.shim_shmem_lock.borrow_mut(), |l| {
884            l.as_ref().map(|l| {
885                let guard = unsafe { &mut *l.get() };
889                guard.deref_mut()
890            })
891        })
892        .ok()
893    }
894
895    pub fn tsc(&self) -> &Tsc {
898        &self.tsc
899    }
900
901    pub fn get_packet_device(&self, address: Ipv4Addr) -> Ref<'_, dyn PacketDevice> {
907        if address == Ipv4Addr::LOCALHOST {
908            self.net_ns.localhost.borrow()
909        } else if address == self.default_ip() {
910            self.net_ns.internet.borrow()
911        } else {
912            self.router.borrow()
913        }
914    }
915
916    pub fn notify_router_has_packets(&self) {
919        self.relay_inet_in.notify(self);
920    }
921
922    pub fn notify_socket_has_packets(&self, addr: Ipv4Addr, socket: &InetSocket) {
930        if self.in_notify_socket_has_packets.replace(&self.root, true) {
931            panic!("Recursively calling host.notify_socket_has_packets()");
932        }
933
934        if let Some(iface) = self.interface_borrow(addr) {
935            iface.add_data_source(socket);
936            match addr {
937                Ipv4Addr::LOCALHOST => self.relay_loopback.notify(self),
938                _ => self.relay_inet_out.notify(self),
939            };
940        }
941
942        self.in_notify_socket_has_packets.set(&self.root, false);
943    }
944
945    pub fn process_session_id_of_group_id(&self, group_id: ProcessId) -> Option<ProcessId> {
947        let processes = self.processes.borrow();
948        for processrc in processes.values() {
949            let process = processrc.borrow(&self.root);
950            if process.group_id() == group_id {
951                return Some(process.session_id());
952            }
953        }
954        None
955    }
956
957    pub fn preload_paths(&self) -> &[PathBuf] {
959        &self.preload_paths
960    }
961}
962
963impl Drop for Host {
964    fn drop(&mut self) {
965        assert!(self.shim_shmem_lock.borrow().is_none());
969    }
970}
971
972mod export {
973    use std::{os::raw::c_char, time::Duration};
974
975    use libc::{in_addr_t, in_port_t};
976    use rand::{Rng, RngCore};
977    use shadow_shim_helper_rs::shim_shmem;
978
979    use super::*;
980    use crate::cshadow::{CEmulatedTime, CSimulationTime};
981    use crate::network::packet::IanaProtocol;
982
983    #[unsafe(no_mangle)]
984    pub unsafe extern "C-unwind" fn host_execute(hostrc: *const Host, until: CEmulatedTime) {
985        let hostrc = unsafe { hostrc.as_ref().unwrap() };
986        let until = EmulatedTime::from_c_emutime(until).unwrap();
987        hostrc.execute(until)
988    }
989
990    #[unsafe(no_mangle)]
991    pub unsafe extern "C-unwind" fn host_nextEventTime(hostrc: *const Host) -> CEmulatedTime {
992        let hostrc = unsafe { hostrc.as_ref().unwrap() };
993        EmulatedTime::to_c_emutime(hostrc.next_event_time())
994    }
995
996    #[unsafe(no_mangle)]
997    pub unsafe extern "C-unwind" fn host_getNewPacketID(hostrc: *const Host) -> u64 {
998        let hostrc = unsafe { hostrc.as_ref().unwrap() };
999        hostrc.get_new_packet_id()
1000    }
1001
1002    #[unsafe(no_mangle)]
1003    pub unsafe extern "C-unwind" fn host_freeAllApplications(hostrc: *const Host) {
1004        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1005        hostrc.free_all_applications()
1006    }
1007
1008    #[unsafe(no_mangle)]
1009    pub unsafe extern "C-unwind" fn host_getID(hostrc: *const Host) -> HostId {
1010        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1011        hostrc.id()
1012    }
1013
1014    #[unsafe(no_mangle)]
1017    pub unsafe extern "C-unwind" fn host_getTsc(host: *const Host) -> *const Tsc {
1018        let hostrc = unsafe { host.as_ref().unwrap() };
1019        hostrc.tsc()
1020    }
1021
1022    #[unsafe(no_mangle)]
1023    pub unsafe extern "C-unwind" fn host_getName(hostrc: *const Host) -> *const c_char {
1024        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1025        hostrc.params.hostname.as_ptr()
1026    }
1027
1028    #[unsafe(no_mangle)]
1029    pub unsafe extern "C-unwind" fn host_getDefaultIP(hostrc: *const Host) -> in_addr_t {
1030        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1031        let ip = hostrc.default_ip();
1032        u32::from(ip).to_be()
1033    }
1034
1035    #[unsafe(no_mangle)]
1036    pub unsafe extern "C-unwind" fn host_getNextPacketPriority(
1037        hostrc: *const Host,
1038    ) -> FifoPacketPriority {
1039        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1040        hostrc.get_next_packet_priority()
1041    }
1042
1043    #[unsafe(no_mangle)]
1044    pub unsafe extern "C-unwind" fn host_autotuneReceiveBuffer(hostrc: *const Host) -> bool {
1045        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1046        hostrc.params.autotune_recv_buf
1047    }
1048
1049    #[unsafe(no_mangle)]
1050    pub unsafe extern "C-unwind" fn host_autotuneSendBuffer(hostrc: *const Host) -> bool {
1051        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1052        hostrc.params.autotune_send_buf
1053    }
1054
1055    #[unsafe(no_mangle)]
1056    pub unsafe extern "C-unwind" fn host_getConfiguredRecvBufSize(hostrc: *const Host) -> u64 {
1057        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1058        hostrc.params.init_sock_recv_buf_size
1059    }
1060
1061    #[unsafe(no_mangle)]
1062    pub unsafe extern "C-unwind" fn host_getConfiguredSendBufSize(hostrc: *const Host) -> u64 {
1063        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1064        hostrc.params.init_sock_send_buf_size
1065    }
1066
1067    #[unsafe(no_mangle)]
1068    pub unsafe extern "C-unwind" fn host_getUpstreamRouter(hostrc: *const Host) -> *mut Router {
1069        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1070        &mut *hostrc.upstream_router_borrow_mut()
1071    }
1072
1073    #[unsafe(no_mangle)]
1074    pub unsafe extern "C-unwind" fn host_get_bw_down_kiBps(hostrc: *const Host) -> u64 {
1075        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1076        hostrc.bw_down_kiBps()
1077    }
1078
1079    #[unsafe(no_mangle)]
1080    pub unsafe extern "C-unwind" fn host_get_bw_up_kiBps(hostrc: *const Host) -> u64 {
1081        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1082        hostrc.bw_up_kiBps()
1083    }
1084
1085    #[unsafe(no_mangle)]
1088    pub unsafe extern "C-unwind" fn host_getDataPath(hostrc: *const Host) -> *const c_char {
1089        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1090        hostrc.data_dir_path_cstring.as_ptr()
1091    }
1092
1093    #[unsafe(no_mangle)]
1094    pub unsafe extern "C-unwind" fn host_disassociateInterface(
1095        hostrc: *const Host,
1096        c_protocol: cshadow::ProtocolType,
1097        bind_ip: in_addr_t,
1098        bind_port: in_port_t,
1099        peer_ip: in_addr_t,
1100        peer_port: in_port_t,
1101    ) {
1102        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1103
1104        let bind_ip = Ipv4Addr::from(u32::from_be(bind_ip));
1105        let peer_ip = Ipv4Addr::from(u32::from_be(peer_ip));
1106        let bind_port = u16::from_be(bind_port);
1107        let peer_port = u16::from_be(peer_port);
1108
1109        let bind_addr = SocketAddrV4::new(bind_ip, bind_port);
1110        let peer_addr = SocketAddrV4::new(peer_ip, peer_port);
1111
1112        let protocol = IanaProtocol::from(c_protocol);
1113
1114        hostrc
1116            .net_ns
1117            .disassociate_interface(protocol, bind_addr, peer_addr);
1118    }
1119
1120    #[unsafe(no_mangle)]
1121    pub unsafe extern "C-unwind" fn host_getRandomFreePort(
1122        hostrc: *const Host,
1123        c_protocol: cshadow::ProtocolType,
1124        interface_ip: in_addr_t,
1125        peer_ip: in_addr_t,
1126        peer_port: in_port_t,
1127    ) -> in_port_t {
1128        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1129
1130        let interface_ip = Ipv4Addr::from(u32::from_be(interface_ip));
1131        let peer_addr = SocketAddrV4::new(
1132            Ipv4Addr::from(u32::from_be(peer_ip)),
1133            u16::from_be(peer_port),
1134        );
1135
1136        let protocol = IanaProtocol::from(c_protocol);
1137
1138        hostrc
1139            .net_ns
1140            .get_random_free_port(
1141                protocol,
1142                interface_ip,
1143                peer_addr,
1144                hostrc.random.borrow_mut().deref_mut(),
1145            )
1146            .unwrap_or(0)
1147            .to_be()
1148    }
1149
1150    #[unsafe(no_mangle)]
1156    pub unsafe extern "C-unwind" fn host_getFutexTable(hostrc: *const Host) -> *mut FutexTable {
1157        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1158        &mut *hostrc.futextable_borrow_mut()
1159    }
1160
1161    #[unsafe(no_mangle)]
1163    pub unsafe extern "C-unwind" fn host_getProcess(
1164        host: *const Host,
1165        virtual_pid: libc::pid_t,
1166    ) -> *const Process {
1167        let host = unsafe { host.as_ref().unwrap() };
1168        let virtual_pid = ProcessId::try_from(virtual_pid).unwrap();
1169        host.process_borrow(virtual_pid)
1170            .map(|x| std::ptr::from_ref(&*x.borrow(host.root())))
1171            .unwrap_or(std::ptr::null_mut())
1172    }
1173
1174    #[unsafe(no_mangle)]
1183    pub unsafe extern "C-unwind" fn host_getThread(
1184        host: *const Host,
1185        virtual_tid: libc::pid_t,
1186    ) -> *const Thread {
1187        let host = unsafe { host.as_ref().unwrap() };
1188        let tid = ThreadId::try_from(virtual_tid).unwrap();
1189        for process in host.processes.borrow().values() {
1190            let process = process.borrow(host.root());
1191            if let Some(thread) = process.thread_borrow(tid) {
1192                let thread = thread.borrow(host.root());
1203                return std::ptr::from_ref(&*thread);
1204            };
1205        }
1206        std::ptr::null_mut()
1207    }
1208
1209    #[unsafe(no_mangle)]
1221    pub unsafe extern "C-unwind" fn host_getShimShmemLock(
1222        hostrc: *const Host,
1223    ) -> *mut shim_shmem::export::ShimShmemHostLock {
1224        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1225        let mut opt_lock = hostrc.shim_shmem_lock.borrow_mut();
1226        let lock = opt_lock.as_mut().unwrap();
1227        unsafe { lock.get().as_mut().unwrap().deref_mut() }
1230    }
1231
1232    #[unsafe(no_mangle)]
1234    pub unsafe extern "C-unwind" fn host_lockShimShmemLock(hostrc: *const Host) {
1235        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1236        hostrc.lock_shmem()
1237    }
1238
1239    #[unsafe(no_mangle)]
1241    pub unsafe extern "C-unwind" fn host_unlockShimShmemLock(hostrc: *const Host) {
1242        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1243        hostrc.unlock_shmem()
1244    }
1245
1246    #[unsafe(no_mangle)]
1251    pub unsafe extern "C-unwind" fn host_getNextDeterministicSequenceValue(
1252        hostrc: *const Host,
1253    ) -> u64 {
1254        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1255        hostrc.get_next_deterministic_sequence_value()
1256    }
1257
1258    #[unsafe(no_mangle)]
1260    pub unsafe extern "C-unwind" fn host_scheduleTaskAtEmulatedTime(
1261        hostrc: *const Host,
1262        task: *mut TaskRef,
1263        time: CEmulatedTime,
1264    ) -> bool {
1265        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1266        let task = unsafe { task.as_ref().unwrap().clone() };
1267        let time = EmulatedTime::from_c_emutime(time).unwrap();
1268        hostrc.schedule_task_at_emulated_time(task, time)
1269    }
1270
1271    #[unsafe(no_mangle)]
1273    pub unsafe extern "C-unwind" fn host_scheduleTaskWithDelay(
1274        hostrc: *const Host,
1275        task: *mut TaskRef,
1276        delay: CSimulationTime,
1277    ) -> bool {
1278        let hostrc = unsafe { hostrc.as_ref().unwrap() };
1279        let task = unsafe { task.as_ref().unwrap().clone() };
1280        let delay = SimulationTime::from_c_simtime(delay).unwrap();
1281        hostrc.schedule_task_with_delay(task, delay)
1282    }
1283
1284    #[unsafe(no_mangle)]
1285    pub unsafe extern "C-unwind" fn host_rngDouble(host: *const Host) -> f64 {
1286        let host = unsafe { host.as_ref().unwrap() };
1287        host.random_mut().random()
1288    }
1289
1290    #[unsafe(no_mangle)]
1292    pub extern "C-unwind" fn host_rngNextNBytes(host: *const Host, buf: *mut u8, len: usize) {
1293        let host = unsafe { host.as_ref().unwrap() };
1294        let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
1295        host.random_mut().fill_bytes(buf);
1296    }
1297
1298    #[unsafe(no_mangle)]
1299    pub extern "C-unwind" fn host_paramsCpuFrequencyHz(host: *const Host) -> u64 {
1300        let host = unsafe { host.as_ref().unwrap() };
1301        host.params.cpu_frequency
1302    }
1303
1304    #[unsafe(no_mangle)]
1305    pub extern "C-unwind" fn host_addDelayNanos(host: *const Host, delay_nanos: u64) {
1306        let host = unsafe { host.as_ref().unwrap() };
1307        let delay = Duration::from_nanos(delay_nanos);
1308        host.cpu.borrow_mut().add_delay(delay);
1309    }
1310
1311    #[unsafe(no_mangle)]
1312    pub unsafe extern "C-unwind" fn host_socketWantsToSend(
1313        hostrc: *const Host,
1314        socket: *const InetSocket,
1315        addr: in_addr_t,
1316    ) {
1317        let host = unsafe { hostrc.as_ref().unwrap() };
1318        let socket = unsafe { socket.as_ref().unwrap() };
1319        let addr = u32::from_be(addr).into();
1320        host.notify_socket_has_packets(addr, socket);
1321    }
1322
1323    #[unsafe(no_mangle)]
1324    pub unsafe extern "C-unwind" fn host_continue(
1325        host: *const Host,
1326        pid: libc::pid_t,
1327        tid: libc::pid_t,
1328    ) {
1329        let host = unsafe { host.as_ref().unwrap() };
1330        host.resume(pid.try_into().unwrap(), tid.try_into().unwrap())
1331    }
1332}