Skip to content

Commit

Permalink
i#6508 context switches: Add invariant checker unit tests
Browse files Browse the repository at this point in the history
Adds some invariant checker unit tests for kernel context switch traces.

Adjusts some invariant checks to account for kernel context switch traces.

Issue: #6508
  • Loading branch information
abhinav92003 committed Mar 28, 2024
1 parent 62af632 commit 518f32f
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 5 deletions.
69 changes: 68 additions & 1 deletion clients/drcachesim/tests/invariant_checker_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2941,6 +2941,72 @@ check_exit_found(void)
return true;
}

bool
check_kernel_context_switch_trace(void)
{
std::cerr << "Testing kernel context switch traces\n";
{
std::vector<memref_t> memrefs = {
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
gen_marker(TID_A, TRACE_MARKER_TYPE_VERSION, TRACE_ENTRY_VERSION_BRANCH_INFO),
gen_instr(TID_A, /*pc=*/1),
gen_marker(TID_A, TRACE_MARKER_TYPE_CONTEXT_SWITCH_START, 0),
gen_instr(TID_A, /*pc=*/10),
gen_instr(TID_A, /*pc=*/11),
gen_marker(TID_A, TRACE_MARKER_TYPE_CONTEXT_SWITCH_END, 0),
gen_instr(TID_A, /*pc=*/2),
gen_exit(TID_A),
};
if (!run_checker(memrefs, false))
return false;
}
{
std::vector<memref_t> memrefs = {
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
gen_marker(TID_A, TRACE_MARKER_TYPE_VERSION, TRACE_ENTRY_VERSION_BRANCH_INFO),
gen_instr(TID_A, /*pc=*/1),
gen_marker(TID_A, TRACE_MARKER_TYPE_CONTEXT_SWITCH_START, 0),
gen_instr(TID_A, /*pc=*/10),
gen_instr(TID_A, /*pc=*/11),
gen_marker(TID_A, TRACE_MARKER_TYPE_CONTEXT_SWITCH_END, 0),
gen_instr(TID_A, /*pc=*/3),
gen_exit(TID_A),
};
if (!run_checker(memrefs, true,
{ "Non-explicit control flow has no marker", TID_A,
/*ref_ordinal=*/9, /*last_timestamp=*/0,
/*instrs_since_last_timestamp=*/4 },
"Failed to catch PC discontinuity after context switch trace")) {
return false;
}
}
{
std::vector<memref_t> memrefs = {
gen_marker(TID_A, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, 64),
gen_marker(TID_A, TRACE_MARKER_TYPE_PAGE_SIZE, 4096),
gen_marker(TID_A, TRACE_MARKER_TYPE_VERSION, TRACE_ENTRY_VERSION_BRANCH_INFO),
gen_instr(TID_A, /*pc=*/1),
gen_marker(TID_A, TRACE_MARKER_TYPE_CONTEXT_SWITCH_START, 0),
gen_instr(TID_A, /*pc=*/10),
gen_instr(TID_A, /*pc=*/12),
gen_marker(TID_A, TRACE_MARKER_TYPE_CONTEXT_SWITCH_END, 0),
gen_instr(TID_A, /*pc=*/2),
gen_exit(TID_A),
};
if (!run_checker(
memrefs, true,
{ "Non-explicit control flow has no marker", TID_A,
/*ref_ordinal=*/7, /*last_timestamp=*/0,
/*instrs_since_last_timestamp=*/3 },
"Failed to catch PC discontinuity inside context switch trace")) {
return false;
}
}
return true;
}

bool
check_kernel_syscall_trace(void)
{
Expand Down Expand Up @@ -3377,7 +3443,8 @@ test_main(int argc, const char *argv[])
check_branch_decoration() && check_filter_endpoint() &&
check_timestamps_increase_monotonically() &&
check_read_write_records_match_operands() && check_exit_found() &&
check_kernel_syscall_trace() && check_has_instructions()) {
check_kernel_syscall_trace() && check_has_instructions() &&
check_kernel_context_switch_trace()) {
std::cerr << "invariant_checker_test passed\n";
return 0;
}
Expand Down
30 changes: 26 additions & 4 deletions clients/drcachesim/tools/invariant_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,12 +536,29 @@ invariant_checker_t::parallel_shard_memref(void *shard_data, const memref_t &mem
shard->pre_syscall_trace_instr_ = {};
}
}
if (memref.marker.type == TRACE_TYPE_MARKER &&
memref.marker.marker_type == TRACE_MARKER_TYPE_CONTEXT_SWITCH_START) {
report_if_false(shard, !shard->between_kernel_context_switch_markers_,
"Nested kernel context switch traces are not expected");
shard->pre_context_switch_trace_instr_ = shard->prev_instr_;
shard->between_kernel_context_switch_markers_ = true;
}
if (memref.marker.type == TRACE_TYPE_MARKER &&
memref.marker.marker_type == TRACE_MARKER_TYPE_CONTEXT_SWITCH_END) {
report_if_false(shard, shard->between_kernel_context_switch_markers_,
"Found kernel context switch trace end without start");
shard->between_kernel_context_switch_markers_ = false;
// For future checks, pretend that the previous instr was the instr just
// before the context switch trace start.
if (shard->pre_context_switch_trace_instr_.memref.instr.addr > 0) {
shard->prev_instr_ = shard->pre_context_switch_trace_instr_;
shard->pre_context_switch_trace_instr_ = {};
}
}
if (!is_a_unit_test(shard)) {
// XXX: between_kernel_syscall_trace_markers_ does not track the
// TRACE_MARKER_TYPE_CONTEXT_SWITCH_* markers. If the invariant checker is run
// with dynamic injection of context switch sequences this will throw an error.
report_if_false(shard,
shard->between_kernel_syscall_trace_markers_ ==
(shard->between_kernel_syscall_trace_markers_ ||
shard->between_kernel_context_switch_markers_) ==
shard->stream->is_record_kernel(),
"Stream is_record_kernel() inaccurate");
}
Expand Down Expand Up @@ -1353,6 +1370,11 @@ invariant_checker_t::check_for_pc_discontinuity(
(shard->prev_entry_.marker.type == TRACE_TYPE_MARKER &&
shard->prev_entry_.marker.marker_type ==
TRACE_MARKER_TYPE_SYSCALL_TRACE_START)) ||
// First instr of kernel context switch trace.
(shard->between_kernel_context_switch_markers_ &&
(shard->prev_entry_.marker.type == TRACE_TYPE_MARKER &&
shard->prev_entry_.marker.marker_type ==
TRACE_MARKER_TYPE_CONTEXT_SWITCH_START)) ||
// String loop.
(prev_instr_trace_pc == cur_pc &&
(cur_memref_info.memref.instr.type == TRACE_TYPE_INSTR_NO_FETCH ||
Expand Down
2 changes: 2 additions & 0 deletions clients/drcachesim/tools/invariant_checker.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ class invariant_checker_t : public analysis_tool_t {
int expected_read_records_ = 0;
int expected_write_records_ = 0;
bool between_kernel_syscall_trace_markers_ = false;
bool between_kernel_context_switch_markers_ = false;
instr_info_t pre_syscall_trace_instr_;
instr_info_t pre_context_switch_trace_instr_;
// Relevant when -no_abort_on_invariant_error.
uint64_t error_count_ = 0;
};
Expand Down

0 comments on commit 518f32f

Please sign in to comment.