Skip to content

Instantly share code, notes, and snippets.

@jorgeortiz85
Last active December 25, 2015 11:29
Show Gist options
  • Save jorgeortiz85/6969337 to your computer and use it in GitHub Desktop.
Save jorgeortiz85/6969337 to your computer and use it in GitHub Desktop.
Measuring kernel interrupt frequencies in Rust. Based on http://www.advenage.com/topics/linux-timer-interrupt-frequency.php
use std::libc::{c_int, c_ulong, c_void, exit, puts};
struct timeval {
tv_sec: i64,
tv_usec: i64
}
struct itimerval {
it_interval: timeval,
it_value: timeval
}
struct sigaction_t {
sa_handler: extern "C" fn(c_int) -> *c_void,
sa_mask: [c_ulong, ..16],
sa_flags: c_int,
sa_sigaction: extern fn(c_int, *c_void, *c_void) -> *c_void
}
#[no_link]
#[abi = "cdecl"]
extern {
fn sigaction(sig: c_int, in_: *sigaction_t, out: *sigaction_t) -> c_int;
fn setitimer(which: c_int, new_value: *itimerval, old_value: *itimerval) -> c_int;
fn gettimeofday(tv: *timeval, tz: *c_void) -> c_int;
}
static SIGALRM: c_int = 14;
static ITIMER_REAL: c_int = 0;
static USECREQ: i64 = 250;
static LOOPS: u64 = 1000;
static mut cnt: u64 = 0;
static mut ts_first: timeval = timeval {
tv_sec: 0,
tv_usec: 0
};
unsafe fn cast_null<G>() -> G {
std::cast::transmute(0)
}
#[fixed_stack_segment]
unsafe fn rputs(_str: &str) {
_str.to_c_str().with_ref(|s| puts(s));
}
#[abi = "cdecl"]
extern fn event_handler(signum: c_int) -> *c_void {
unsafe {
if cnt == 0 {
gettimeofday(&ts_first, cast_null());
}
cnt += 1;
if cnt >= LOOPS {
let mut ts_now = timeval {
tv_sec: 0,
tv_usec: 0
};
let mut diff = timeval {
tv_sec: 0,
tv_usec: 0
};
setitimer(ITIMER_REAL, cast_null(), cast_null());
gettimeofday(&ts_now, cast_null());
// timersub is a macro so we can't call it via extern
//
// timersub(&ts_now, &ts_first, &diff);
diff.tv_sec = ts_now.tv_sec - ts_first.tv_sec;
diff.tv_usec = ts_now.tv_usec - ts_first.tv_usec;
if diff.tv_usec < 0 {
diff.tv_sec -= 1;
diff.tv_usec += 1000000;
}
let udiff: u64 = ((diff.tv_sec as u64) * 1000000) + (diff.tv_usec as u64);
let delta: float = ((udiff as float) / (cnt as float)) / 1000000.0;
let hz: uint = (1.0 / delta) as uint;
let limit: uint = (1.0 / ((USECREQ as float) / 1000000.0)) as uint;
let extra = if hz >= limit { "or higher" } else { "" };
rputs(fmt!("kernel timer interrupt frequency is approx. %u Hz %s", hz, extra));
exit(0);
}
cast_null()
}
}
#[fixed_stack_segment]
unsafe fn unsafe_main() {
let sa = sigaction_t {
sa_handler: event_handler,
sa_mask: [0, ..16],
sa_flags: 0,
sa_sigaction: cast_null()
};
sigaction(SIGALRM, &sa, cast_null());
let timer = itimerval {
it_interval: timeval {
tv_sec: 0,
tv_usec: USECREQ
},
it_value: timeval {
tv_sec: 0,
tv_usec: USECREQ
}
};
setitimer(ITIMER_REAL, &timer, cast_null());
while(true) {};
}
fn main() {
unsafe { unsafe_main() };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment