diff --git a/src/lib.rs b/src/lib.rs index 9593b12..f9e6caf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use core_affinity::CoreId; use serde::Deserialize; use std::fmt::Display; +use syscalls::Sysno; pub mod worker; @@ -42,6 +43,18 @@ fn default_duration() -> u64 { 0 } +fn default_syscalls_arrival_rate() -> f64 { + 0.0 +} + +fn default_syscalls_tight_loop() -> bool { + false +} + +fn default_syscalls_syscall_nr() -> u32 { + Sysno::getpid as u32 +} + /// Workload specific configuration, contains one enum value for each /// workload type. #[derive(Debug, Copy, Clone, Deserialize)] @@ -69,7 +82,16 @@ pub enum Workload { /// How to invoke syscalls Syscalls { /// How often to invoke a syscall. + #[serde(default = "default_syscalls_arrival_rate")] arrival_rate: f64, + + /// Run in a tight loop + #[serde(default = "default_syscalls_tight_loop")] + tight_loop: bool, + + /// Which syscall to trigger + #[serde(default = "default_syscalls_syscall_nr")] + syscall_nr: u32, }, /// How to open network connections @@ -295,7 +317,12 @@ mod tests { .. } = config; assert_eq!(restart_interval, 10); - if let Workload::Syscalls { arrival_rate } = workload { + if let Workload::Syscalls { + arrival_rate, + tight_loop, + syscall_nr, + } = workload + { assert_eq!(arrival_rate, 10.0); } else { panic!("wrong workload type found"); diff --git a/src/worker/syscalls.rs b/src/worker/syscalls.rs index 9290bc3..0e077bd 100644 --- a/src/worker/syscalls.rs +++ b/src/worker/syscalls.rs @@ -1,3 +1,4 @@ +use std::time::{Duration, Instant}; use std::{fmt::Display, thread, time}; use core_affinity::CoreId; @@ -22,11 +23,11 @@ impl SyscallsWorker { } } - fn do_syscall(&self) -> std::io::Result<()> { - match unsafe { syscall!(Sysno::getpid) } { + fn do_syscall(&self, syscall: Sysno) -> std::io::Result<()> { + match unsafe { syscall!(syscall) } { Ok(_) => Ok(()), Err(err) => { - warn!("Syscall failed: {}", err); + info!("Syscall failed: {}", err); Ok(()) } } @@ -37,16 +38,45 @@ impl Worker for SyscallsWorker { fn run_payload(&self) -> Result<(), WorkerError> { info!("{self}"); - let Workload::Syscalls { arrival_rate } = self.workload.workload else { + let mut counter = 0; + let mut start = Instant::now(); + + let Workload::Syscalls { + arrival_rate, + tight_loop, + syscall_nr, + } = self.workload.workload + else { unreachable!() }; + let syscall = Sysno::from(syscall_nr); + info!("Running syscall {syscall}"); + loop { let worker = *self; - thread::spawn(move || { - worker.do_syscall().unwrap(); - }); + if start.elapsed().as_secs() > 10 { + warn!( + "CPU {}, {}", + self.config.cpu.id, + counter / start.elapsed().as_secs() + ); + start = Instant::now(); + counter = 0; + } + + counter += 1; + // Do the syscall directly, without spawning a thread (it would + // introduce too much overhead for a quick syscall). + worker.do_syscall(syscall).unwrap(); + + // If running in a tight loop, go to the next iteration + if tight_loop { + continue; + } + + // Otherwise calculate waiting time let interval: f64 = thread_rng().sample(Exp::new(arrival_rate).unwrap()); info!(