Skip to content

Commit c2ba256

Browse files
authored
i#7157: Inject syscall templates dynamically in scheduler (#7277)
Adds support to the drmemtrace scheduler for injecting system call trace templates dynamically during scheduling. This obviates the need to create a separate statically-injected trace with system call trace templates. Reuses context switch trace injection code to the extent possible. Adds a new analyzer flag -sched_syscall_file and new scheduler_options_t fields to allow specifying the system call trace template file. Adds a mock system call template file generated using the burst_syscall_inject test (slightly modified to use sysnums that match the checked-in test trace). Adds various unit tests: a new scheduler unit test that verifies dynamic syscall trace injection and its effect on scheduling, analyzer tests that use -sched_syscall_file for dynamic injection in core-sharded and non-core-sharded modes, and an invariant checker test on the added mock system call template file. Issue: #7157
1 parent 61db1c8 commit c2ba256

18 files changed

Lines changed: 678 additions & 170 deletions

api/docs/release.dox

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ Further non-compatibility-affecting changes include:
141141
instructions in the trace. This works for traces that have embedded instruction
142142
encodings in them, and also for legacy traces without embedded encodings where the
143143
encodings are obtained from the application binaries instead.
144+
- Added a new drmemtrace analyzer flag -sched_syscall_file to allow specifying the
145+
system call trace template file to be used for dynamic injection of system call trace
146+
templates. Added similar options for the drmemtrace scheduler: #dynamorio::drmemtrace::
147+
scheduler_tmpl_t::scheduler_options_t::kernel_syscall_trace_path, and #dynamorio::
148+
drmemtrace::scheduler_tmpl_t::scheduler_options_t::kernel_syscall_reader.
144149

145150
**************************************************
146151
<hr>

clients/drcachesim/analyzer.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -320,19 +320,22 @@ analyzer_tmpl_t<RecordType, ReaderType>::init_scheduler_common(
320320
sched_ops.single_lockstep_output = true;
321321
worker_count_ = 1;
322322
}
323-
} else if (parallel_) {
324-
sched_ops = sched_type_t::make_scheduler_parallel_options(verbosity_);
325-
sched_ops.replay_as_traced_istream = options.replay_as_traced_istream;
326-
sched_ops.read_inputs_in_init = options.read_inputs_in_init;
327-
if (worker_count_ <= 0)
328-
worker_count_ = std::thread::hardware_concurrency();
329-
output_count = worker_count_;
330323
} else {
331-
sched_ops = sched_type_t::make_scheduler_serial_options(verbosity_);
324+
if (parallel_) {
325+
sched_ops = sched_type_t::make_scheduler_parallel_options(verbosity_);
326+
if (worker_count_ <= 0)
327+
worker_count_ = std::thread::hardware_concurrency();
328+
output_count = worker_count_;
329+
} else {
330+
sched_ops = sched_type_t::make_scheduler_serial_options(verbosity_);
331+
worker_count_ = 1;
332+
output_count = 1;
333+
}
334+
// As noted in the init_scheduler_common() header comment, we preserve only
335+
// some select fields.
332336
sched_ops.replay_as_traced_istream = options.replay_as_traced_istream;
333337
sched_ops.read_inputs_in_init = options.read_inputs_in_init;
334-
worker_count_ = 1;
335-
output_count = 1;
338+
sched_ops.kernel_syscall_trace_path = options.kernel_syscall_trace_path;
336339
}
337340
sched_mapping_ = options.mapping;
338341
if (scheduler_.init(workloads, output_count, std::move(sched_ops)) !=

clients/drcachesim/analyzer.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,22 +217,25 @@ template <typename RecordType, typename ReaderType> class analyzer_tmpl_t {
217217
operator=(const analyzer_worker_data_t &) = delete;
218218
};
219219

220+
// See comment on init_scheduler_common() for some noteworthy details.
220221
bool
221222
init_scheduler(const std::vector<std::string> &trace_paths,
222223
// To include all threads/shards, use empty sets.
223224
const std::set<memref_tid_t> &only_threads,
224225
const std::set<int> &only_shards, int output_limit, int verbosity,
225226
typename sched_type_t::scheduler_options_t options);
226227

227-
// For core-sharded, worker_count_ must be set prior to calling this; for parallel
228-
// mode if it is not set it will be set to the underlying core count.
229-
// For core-sharded, all of "options" is used; otherwise, only the
230-
// read_inputs_in_init field is preserved.
228+
// See comment on init_scheduler_common() for some noteworthy details.
231229
bool
232230
init_scheduler(std::unique_ptr<ReaderType> reader,
233231
std::unique_ptr<ReaderType> reader_end, int verbosity,
234232
typename sched_type_t::scheduler_options_t options);
235233

234+
// For core-sharded, worker_count_ must be set prior to calling this; for parallel
235+
// mode if it is not set it will be set to the underlying core count.
236+
// For core-sharded, all of "options" is used; otherwise, the
237+
// read_inputs_in_init, replay_as_traced_istream, and kernel_syscall_trace_path
238+
// fields are preserved.
236239
bool
237240
init_scheduler_common(std::vector<typename sched_type_t::input_workload_t> &workloads,
238241
typename sched_type_t::scheduler_options_t options);

clients/drcachesim/analyzer_multi.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ analyzer_multi_tmpl_t<RecordType, ReaderType>::analyzer_multi_tmpl_t()
571571
#endif
572572
}
573573

574+
sched_ops.kernel_syscall_trace_path = op_sched_syscall_file.get_value();
575+
574576
if (!indirs.empty()) {
575577
std::vector<std::string> tracedirs;
576578
for (const std::string &indir : indirs)

clients/drcachesim/common/memtrace_stream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class memtrace_stream_t {
113113
*/
114114
SCHED_STAT_HIT_OUTPUT_LIMIT,
115115
/**
116-
* Counts the instances when the kernel context switch sequence was injected.
116+
* Counts the instances when the kernel context switch sequences were injected.
117117
*/
118118
SCHED_STAT_KERNEL_SWITCH_SEQUENCE_INJECTIONS,
119119
/** Count of statistic types. */

clients/drcachesim/common/options.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,12 +1039,20 @@ droption_t<std::string>
10391039
#endif
10401040
droption_t<std::string> op_sched_switch_file(
10411041
DROPTION_SCOPE_FRONTEND, "sched_switch_file", "",
1042-
"Path to file holding context switch sequences",
1042+
"Path to file holding kernel context switch sequences",
10431043
"Applies to -core_sharded and -core_serial. Path to file holding context switch "
10441044
"sequences. The file can contain multiple sequences each with regular trace headers "
10451045
"and the sequence proper bracketed by TRACE_MARKER_TYPE_CONTEXT_SWITCH_START and "
10461046
"TRACE_MARKER_TYPE_CONTEXT_SWITCH_END markers.");
10471047

1048+
droption_t<std::string> op_sched_syscall_file(
1049+
DROPTION_SCOPE_FRONTEND, "sched_syscall_file", "",
1050+
"Path to file holding kernel system call sequences",
1051+
"Path to file holding system call sequences. The file can contain multiple "
1052+
"sequences each with regular trace headers and the sequence proper bracketed by "
1053+
"TRACE_MARKER_TYPE_SYSCALL_TRACE_START and TRACE_MARKER_TYPE_SYSCALL_TRACE_END "
1054+
"markers.");
1055+
10481056
droption_t<bool> op_sched_randomize(
10491057
DROPTION_SCOPE_FRONTEND, "sched_randomize", false,
10501058
"Pick next inputs randomly on context switches",

clients/drcachesim/common/options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ extern dynamorio::droption::droption_t<std::string> op_replay_file;
216216
extern dynamorio::droption::droption_t<std::string> op_cpu_schedule_file;
217217
#endif
218218
extern dynamorio::droption::droption_t<std::string> op_sched_switch_file;
219+
extern dynamorio::droption::droption_t<std::string> op_sched_syscall_file;
219220
extern dynamorio::droption::droption_t<bool> op_sched_randomize;
220221
extern dynamorio::droption::droption_t<bool> op_sched_disable_direct_switches;
221222
extern dynamorio::droption::droption_t<bool> op_sched_infinite_timeouts;

clients/drcachesim/scheduler/scheduler.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,31 @@ template <typename RecordType, typename ReaderType> class scheduler_tmpl_t {
829829
* when raising this value on uneven inputs.
830830
*/
831831
double exit_if_fraction_inputs_left = 0.1;
832+
/**
833+
* Input file containing template sequences of kernel system call code.
834+
* Each sequence must start with a #TRACE_MARKER_TYPE_SYSCALL_TRACE_START
835+
* marker and end with #TRACE_MARKER_TYPE_SYSCALL_TRACE_END.
836+
* The value of each marker must hold the system call number for the system call
837+
* it corresponds to. Sequences for multiple system calls are concatenated into a
838+
* single file. Each sequence should be in the regular offline drmemtrace format.
839+
* Whenever a #TRACE_MARKER_TYPE_SYSCALL marker is encountered in a trace, if a
840+
* corresponding sequence with the same marker value exists it is inserted into
841+
* the output stream after the #TRACE_MARKER_TYPE_SYSCALL marker.
842+
* The same file (or reader) must be passed when replaying as this kernel
843+
* code is not stored when recording.
844+
* An alternative to passing the file path is to pass #kernel_syscall_reader
845+
* and #kernel_syscall_reader_end.
846+
*/
847+
std::string kernel_syscall_trace_path;
848+
/**
849+
* An alternative to #kernel_syscall_trace_path is to pass a reader and
850+
* #kernel_syscall_reader_end. See the description of #kernel_syscall_trace_path.
851+
* This field is only examined if #kernel_syscall_trace_path is empty.
852+
* The scheduler will call the init() function for the reader.
853+
*/
854+
std::unique_ptr<ReaderType> kernel_syscall_reader;
855+
/** The end reader for #kernel_syscall_reader. */
856+
std::unique_ptr<ReaderType> kernel_syscall_reader_end;
832857
// When adding new options, also add to print_configuration().
833858
};
834859

clients/drcachesim/scheduler/scheduler_dynamic.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* **********************************************************
2-
* Copyright (c) 2023-2024 Google, Inc. All rights reserved.
2+
* Copyright (c) 2023-2025 Google, Inc. All rights reserved.
33
* **********************************************************/
44

55
/*
@@ -596,16 +596,10 @@ scheduler_dynamic_tmpl_t<RecordType, ReaderType>::process_marker(
596596
case TRACE_MARKER_TYPE_CONTEXT_SWITCH_START:
597597
outputs_[output].in_context_switch_code = true;
598598
break;
599-
case TRACE_MARKER_TYPE_SYSCALL_TRACE_START:
600-
outputs_[output].in_syscall_code = true;
601-
break;
602599
case TRACE_MARKER_TYPE_CONTEXT_SWITCH_END:
603600
// We have to delay until the next record.
604601
outputs_[output].hit_switch_code_end = true;
605602
break;
606-
case TRACE_MARKER_TYPE_SYSCALL_TRACE_END:
607-
outputs_[output].in_syscall_code = false;
608-
break;
609603
case TRACE_MARKER_TYPE_TIMESTAMP:
610604
// Syscall sequences are not expected to have a timestamp.
611605
assert(!outputs_[output].in_syscall_code);

0 commit comments

Comments
 (0)