Skip to content
7 changes: 6 additions & 1 deletion src/lind-boot/src/perf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub static LIND_BOOT_COUNTERS: &[&Counter] = &[&GRATE_CALLBACK_TRAMPOLINE, &TYPE
/// counts.
pub fn perf_init(kind: TimerKind) {
// Configure timer backend (Clock or TSC) for all local counters.

lind_perf::set_timer(all_counters(), kind);
// Reset all accumulated measurements before benchmark runs begin.
lind_perf::reset_all_counters(all_counters());
Expand All @@ -33,7 +34,10 @@ pub fn enable_one_counter(name: &str) {
}

fn all_counters() -> impl Iterator<Item = &'static Counter> {
LIND_BOOT_COUNTERS.iter().copied()
LIND_BOOT_COUNTERS
.iter()
.copied()
.chain(threei::perf::ALL_COUNTERS.iter().copied())
}

/// Get a list of all counter names.
Expand All @@ -46,4 +50,5 @@ pub fn perf_report() {
// Note: `lind_perf::report*` are no-ops when lind-perf is built without
// its internal `enabled` feature.
lind_perf::report(LIND_BOOT_COUNTERS, format!("LIND-BOOT"));
lind_perf::report(threei::perf::ALL_COUNTERS, format!("THREE-I"));
}
1 change: 1 addition & 0 deletions src/threei/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod handler_table;
pub mod perf;
pub mod threei;
pub mod threei_const;

Expand Down
7 changes: 7 additions & 0 deletions src/threei/src/perf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use lind_perf::Counter;

pub static CALL_GRATE_FUNC: Counter = Counter::new("threei::_call_grate_func");
pub static MAKE_SYSCALL: Counter = Counter::new("threei::make_syscall");
pub static RAWPOSIX_DISPATCH: Counter = Counter::new("threei::rawposix_dispatch");

pub static ALL_COUNTERS: &[&Counter] = &[&CALL_GRATE_FUNC, &MAKE_SYSCALL, &RAWPOSIX_DISPATCH];
20 changes: 19 additions & 1 deletion src/threei/src/threei.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::handler_table::{
_check_cage_handler_exists, _get_handler, _rm_cage_from_handler, _rm_grate_from_handler,
copy_handler_table_to_cage_impl, print_handler_table, register_handler_impl,
};
use crate::perf;
use crate::threei_const;

pub const EXIT_SYSCALL: u64 = 60; // exit syscall number. Public for tests.
Expand Down Expand Up @@ -201,6 +202,8 @@ fn _call_grate_func(
arg6: u64,
arg6_cageid: u64,
) -> Option<i32> {
let _timer = lind_perf::get_timer!(perf::CALL_GRATE_FUNC);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are others range gated but not this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_call_grate_func doesn't have access to the syscall_num that was called so we can't gate it.

besides, the rationale for gating make_syscall was to ensure we dont see measurement from other syscalls. _call_grate_func is only called for interposed syscalls, and we can easily have a setup where only the syscall being benchmarked is interposed.


let runtimeid = match get_cage_runtime(grateid) {
Some(r) => r,
None => panic!(
Expand Down Expand Up @@ -412,6 +415,13 @@ pub fn make_syscall(
arg6: u64,
arg6_cageid: u64,
) -> i32 {
// Only enable timers for syscalls that are explicitly benchmarking related (2000-3000)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be cfg'd?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for everything in a 3i file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All cfg's are handled within lind-perf, which has no-op shims when the feature is not enabled. This allows us to not have to use cfg's here.

When building without lind_perf, the get_timer!() just returns None, and will not cause overheads.

let _timer = if syscall_num > 2000 && syscall_num < 3000 {
Some(lind_perf::get_timer!(perf::MAKE_SYSCALL))
} else {
None
};

// Return error if the target cage/grate is exiting. We need to add this check beforehead, because make_syscall will also
// contain cases that can directly redirect a syscall when self_cageid == target_id, which will bypass the handlertable check
if EXITING_TABLE.contains(&target_cageid) && syscall_num != EXIT_SYSCALL {
Expand All @@ -428,9 +438,14 @@ pub fn make_syscall(
if grateid == lind_platform_const::RAWPOSIX_CAGEID
|| grateid == lind_platform_const::WASMTIME_CAGEID
{
let _rpx_dispatch_timer = if syscall_num > 2000 && syscall_num < 3000 {
Some(lind_perf::get_timer!(perf::RAWPOSIX_DISPATCH))
} else {
None
};
let func: RawCallFunc =
unsafe { std::mem::transmute::<u64, RawCallFunc>(in_grate_fn_ptr_u64) };
return func(
let r = func(
self_cageid,
arg1,
arg1_cageid,
Expand All @@ -445,6 +460,9 @@ pub fn make_syscall(
arg6,
arg6_cageid,
);
drop(_rpx_dispatch_timer);

return r;
}
// Threei special case: if the call is an interposed 3i call
if grateid == lind_platform_const::THREEI_CAGEID {
Expand Down