Last active
December 25, 2015 11:29
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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