Skip to content

Commit

Permalink
Merge branch 'master' of github.com:DynamoRIO/dynamorio into i6949-dr…
Browse files Browse the repository at this point in the history
…cachesim-sched-default
  • Loading branch information
derekbruening committed Oct 17, 2024
2 parents 1ea126a + 1afe5eb commit fa2d07c
Show file tree
Hide file tree
Showing 17 changed files with 298 additions and 19 deletions.
4 changes: 4 additions & 0 deletions api/docs/release.dox
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ Further non-compatibility-affecting changes include:
- Added -trace_instr_intervals_file option to the drmemtrace trace analysis tools
framework. The file must be in CSV format containing a <start,duration> tracing
interval per line where start and duration are expressed in number of instructions.
- Added modify_marker_value_filter_t to #dynamorio::drmemtrace::record_filter_t to modify
the value of TRACE_MARKER_TYPE_ markers. This filter takes a list of
<TRACE_MARKER_TYPE_,new_value> and changes every listed marker in the trace to its
corresponding new_value.
- Added trace_analysis_tool::preferred_shard_type() to the drmemtrace framework to
allow switching to core-sharded by default if all tools prefer that mode.
- For the drmemtrace framework, if only core-sharded-preferring tools are enabled
Expand Down
1 change: 1 addition & 0 deletions clients/drcachesim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ add_exported_library(drmemtrace_record_filter STATIC
tools/filter/type_filter.h
tools/filter/encodings2regdeps_filter.h
tools/filter/func_id_filter.h
tools/filter/modify_marker_value_filter.h
tools/filter/null_filter.h)
target_link_libraries(drmemtrace_record_filter drmemtrace_simulator
drmemtrace_schedule_file)
Expand Down
3 changes: 2 additions & 1 deletion clients/drcachesim/analyzer_multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ record_analyzer_multi_t::create_analysis_tool_from_options(const std::string &to
op_filter_cache_size.get_value(), op_filter_trace_types.get_value(),
op_filter_marker_types.get_value(), op_trim_before_timestamp.get_value(),
op_trim_after_timestamp.get_value(), op_encodings2regdeps.get_value(),
op_filter_func_ids.get_value(), op_verbose.get_value());
op_filter_func_ids.get_value(), op_modify_marker_value.get_value(),
op_verbose.get_value());
}
ERRMSG("Usage error: unsupported record analyzer type \"%s\". Only " RECORD_FILTER
" is supported.\n",
Expand Down
9 changes: 9 additions & 0 deletions clients/drcachesim/common/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,15 @@ droption_t<std::string>
"for the listed function IDs and removes those belonging to "
"unlisted function IDs.");

droption_t<std::string> op_modify_marker_value(
DROPTION_SCOPE_FRONTEND, "filter_modify_marker_value", "",
"Comma-separated pairs of integers representing <TRACE_MARKER_TYPE_, new_value>.",
"This option is for -tool " RECORD_FILTER ". It modifies the value of all listed "
"TRACE_MARKER_TYPE_ markers in the trace with their corresponding new_value. "
"The list must have an even size. Example: -filter_modify_marker_value 3,24,18,2048 "
"sets all TRACE_MARKER_TYPE_CPU_ID == 3 in the trace to core 24 and "
"TRACE_MARKER_TYPE_PAGE_SIZE == 18 to 2k.");

droption_t<uint64_t> op_trim_before_timestamp(
DROPTION_SCOPE_ALL, "trim_before_timestamp", 0, 0,
(std::numeric_limits<uint64_t>::max)(),
Expand Down
1 change: 1 addition & 0 deletions clients/drcachesim/common/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ extern dynamorio::droption::droption_t<std::string> op_filter_trace_types;
extern dynamorio::droption::droption_t<std::string> op_filter_marker_types;
extern dynamorio::droption::droption_t<bool> op_encodings2regdeps;
extern dynamorio::droption::droption_t<std::string> op_filter_func_ids;
extern dynamorio::droption::droption_t<std::string> op_modify_marker_value;
extern dynamorio::droption::droption_t<uint64_t> op_trim_before_timestamp;
extern dynamorio::droption::droption_t<uint64_t> op_trim_after_timestamp;
extern dynamorio::droption::droption_t<bool> op_abort_on_invariant_error;
Expand Down
3 changes: 3 additions & 0 deletions clients/drcachesim/common/trace_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,9 @@ typedef enum {
// Values below here are available for users to use for custom markers.
} trace_marker_type_t;

// As documented in TRACE_MARKER_TYPE_CPU_ID, this value indicates an unknown CPU.
#define INVALID_CPU_MARKER_VALUE static_cast<uintptr_t>(-1)

/** Constants related to function or system call parameter tracing. */
enum class func_trace_t : uint64_t { // VS2019 won't infer 64-bit with "enum {".
/**
Expand Down
20 changes: 13 additions & 7 deletions clients/drcachesim/docs/drcachesim.dox.in
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ Some of the more important markers are:

- #dynamorio::drmemtrace::TRACE_MARKER_TYPE_KERNEL_XFER - This identifies a system call that changes control flow, such as a signal return.

- #dynamorio::drmemtrace::TRACE_MARKER_TYPE_TIMESTAMP - The marker value provides a timestamp for this point of the trace (in units of microseconds since Jan 1, 1601 UTC). This value can be used to synchronize records from different threads as well as analyze latencies (however, tracing overhead inflates time unevenly, so time deltas should not be considered perfectly representative). It is used in the sequential analysis of a multi-threaded trace.
- #dynamorio::drmemtrace::TRACE_MARKER_TYPE_TIMESTAMP - The marker value provides a timestamp for this point of the trace (in units of microseconds since Jan 1, 1601 UTC). This value can be used to synchronize records from different threads as well as analyze latencies (however, tracing overhead inflates time unevenly, so time deltas should not be considered perfectly representative). It is used in the sequential analysis of a multi-threaded trace. When dynamic scheduling is performed (see \ref sec_drcachesim_sched_dynamic), the original timestamp value is replaced with a synthetic value in order to maintain relative ordering (though the new values should not be relied upon to indicate accurate durations between events).

- #dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID - The marker value contains the CPU identifier on which the subsequent records were collected. It can be used to identify the "as traced" schedule, indicating which threads were on which cores at which times. However, this schedule is not representative and should not be treated as indicating how the application behaves without tracing. See \ref sec_drcachesim_as_traced for further information.
- #dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID - The marker value contains the CPU identifier on which the subsequent records were collected. It can be used to identify the "as traced" schedule, indicating which threads were on which cores at which times. However, this schedule is not representative and should not be treated as indicating how the application behaves without tracing. See \ref sec_drcachesim_as_traced for further information. When dynamic scheduling is performed (see \ref sec_drcachesim_sched_dynamic), the original value of this marker is replaced with the new virtual core identifier.

- #dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_ID, #dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_RETADDR, #dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_ARG, #dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_RETVAL - These markers are used to capture information about function calls. Which functions to capture must be explicitly selected at tracing time. Typical candiates are heap allocation and freeing functions. See \ref sec_drcachesim_funcs.

Expand Down Expand Up @@ -1473,8 +1473,10 @@ While we suggest keeping traces stored as thread-sharded and using the dynamic s
in each run, there is support for running the scheduler once and creating a new set of
stored traces in core-sharded format: essentially switching to hardware-thread-oriented
traces. This is done using the \ref sec_tool_record_filter tool in `-core_sharded` mode.
The #dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID markers are not modified by the
dynamic scheduler, and should be ignored in a newly created core-sharded trace.
The #dynamorio::drmemtrace::TRACE_MARKER_TYPE_TIMESTAMP and
#dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID markers are modified by the dynamic
scheduler to reflect the new schedule. The new timestamps maintain relative ordering
but should not be relied upon to indicate accurate durations between events.
When analyzing core-sharded-on-disk traces, be sure to pass `-no_core_sharded` when
using core-sharded-preferring tools to avoid the trace being re-scheduled yet again.

Expand Down Expand Up @@ -1543,7 +1545,9 @@ through the -cpu_schedule_file option.
\section sec_drcachesim_sched_dynamic Dynamic Scheduling

Instead of using the as-traced schedule, we recommend re-scheduling the traced software
threads using our trace scheduler. Our scheduler essentially serves as an operating
threads using our trace scheduler in
#dynamorio::drmemtrace::scheduler_t::MAP_TO_ANY_OUTPUT mode.
Our scheduler essentially serves as an operating
system scheduler for this purpose, though using simpler schemes. It models separate
runqueues per core with support for binding inputs to certain cores, priorities, idle
time from blocking system calls, migration thresholds, rebalancing runqueues, etc. It
Expand Down Expand Up @@ -1572,8 +1576,10 @@ The downsides include:
thus, timestamp ordering will be followed at context switch points for picking the
next input, but timestamps will not preempt an input.

The #dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID markers are not modified by the
dynamic scheduler, and should be ignored in a dynamic rescheduling.
The #dynamorio::drmemtrace::TRACE_MARKER_TYPE_TIMESTAMP and
#dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID markers are modified by the dynamic
scheduler to reflect the new schedule. The new timestamps maintain relative ordering
but should not be relied upon to indicate accurate durations between events.

********************
\section sec_drcachesim_sched_time Simulated Time
Expand Down
7 changes: 4 additions & 3 deletions clients/drcachesim/scheduler/scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2784,7 +2784,8 @@ scheduler_tmpl_t<RecordType, ReaderType>::pop_from_ready_queue_hold_locks(
// For never-executed inputs we consider their last execution
// to be the very first simulation time, which we can't
// easily initialize until here.
res->last_run_time = outputs_[from_output].initial_cur_time;
res->last_run_time = outputs_[from_output].initial_cur_time->load(
std::memory_order_acquire);
}
VPRINT(this, 5,
"migration check %d to %d: cur=%" PRIu64 " last=%" PRIu64
Expand Down Expand Up @@ -3805,8 +3806,8 @@ scheduler_tmpl_t<RecordType, ReaderType>::next_record(output_ordinal_t output,
cur_time = 1 + outputs_[output].stream->get_output_instruction_ordinal() +
outputs_[output].idle_count;
}
if (outputs_[output].initial_cur_time == 0) {
outputs_[output].initial_cur_time = cur_time;
if (outputs_[output].initial_cur_time->load(std::memory_order_acquire) == 0) {
outputs_[output].initial_cur_time->store(cur_time, std::memory_order_release);
}
// Invalid values for cur_time are checked below.
outputs_[output].cur_time->store(cur_time, std::memory_order_release);
Expand Down
7 changes: 6 additions & 1 deletion clients/drcachesim/scheduler/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1645,6 +1645,9 @@ template <typename RecordType, typename ReaderType> class scheduler_tmpl_t {
cur_time =
std::unique_ptr<std::atomic<uint64_t>>(new std::atomic<uint64_t>());
cur_time->store(0, std::memory_order_relaxed);
initial_cur_time =
std::unique_ptr<std::atomic<uint64_t>>(new std::atomic<uint64_t>());
initial_cur_time->store(0, std::memory_order_relaxed);
record_index = std::unique_ptr<std::atomic<int>>(new std::atomic<int>());
record_index->store(0, std::memory_order_relaxed);
}
Expand Down Expand Up @@ -1693,7 +1696,9 @@ template <typename RecordType, typename ReaderType> class scheduler_tmpl_t {
// Indirected so we can store it in our vector.
std::unique_ptr<std::atomic<uint64_t>> cur_time;
// The first simulation time passed to this output.
uint64_t initial_cur_time = 0;
// This is accessed by other outputs for stealing and rebalancing.
// Indirected so we can store it in our vector.
std::unique_ptr<std::atomic<uint64_t>> initial_cur_time;
// Used for MAP_TO_RECORDED_OUTPUT get_output_cpuid().
int64_t as_traced_cpuid = -1;
// Used for MAP_AS_PREVIOUSLY with live_replay_output_count_.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Estimation of pi is 3.142425985001098

Trace invariant checks passed

Output .* entries from .* entries.

Output format:

<--record#-> <--instr#->: <---tid---> <record details>

------------------------------------------------------------

1 0: +[0-9]+ <marker: version [0-9]>
2 0: +[0-9]+ <marker: filetype 0x[0-9a-f]*>
3 0: +[0-9]+ <marker: cache line size [0-9]*>
4 0: +[0-9]+ <marker: chunk instruction count [0-9]*>
5 0: +[0-9]+ <marker: page size 2048>
6 0: +[0-9]+ <marker: timestamp [0-9]*>
7 0: +[0-9]+ <marker: tid [0-9]* on core unknown>
.*
77 changes: 76 additions & 1 deletion clients/drcachesim/tests/record_filter_unit_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "tools/filter/type_filter.h"
#include "tools/filter/encodings2regdeps_filter.h"
#include "tools/filter/func_id_filter.h"
#include "tools/filter/modify_marker_value_filter.h"
#include "trace_entry.h"
#include "zipfile_ostream.h"

Expand Down Expand Up @@ -600,6 +601,80 @@ test_func_id_filter()
return true;
}

static bool
test_modify_marker_value_filter()
{
constexpr addr_t PC = 0x7f6fdd3ec360;
constexpr addr_t ENCODING = 0xe78948;
constexpr uint64_t NEW_PAGE_SIZE_MARKER_VALUE = 0x800; // 2k pages.
std::vector<test_case_t> entries = {
// Trace shard header.
{ { TRACE_TYPE_HEADER, 0, { 0x1 } }, true, { true } },
{ { TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_VERSION, { 0x2 } }, true, { true } },
{ { TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_FILETYPE,
{ OFFLINE_FILE_TYPE_ARCH_X86_64 | OFFLINE_FILE_TYPE_ENCODINGS |
OFFLINE_FILE_TYPE_SYSCALL_NUMBERS | OFFLINE_FILE_TYPE_BLOCKING_SYSCALLS } },
true,
{ true } },
{ { TRACE_TYPE_THREAD, 0, { 0x4 } }, true, { true } },
{ { TRACE_TYPE_PID, 0, { 0x5 } }, true, { true } },
{ { TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CACHE_LINE_SIZE, { 0x6 } },
true,
{ true } },
{ { TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_PAGE_SIZE, { 0x1000 } }, // 4k pages.
true,
{ false } },
// Overwrite the value of TRACE_MARKER_TYPE_PAGE_SIZE with 0x800 == 2048 == 2k
// page size.
{ { TRACE_TYPE_MARKER,
TRACE_MARKER_TYPE_PAGE_SIZE,
{ NEW_PAGE_SIZE_MARKER_VALUE } },
false,
{ true } },
{ { TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_TIMESTAMP, { 0x7 } }, true, { true } },
{ { TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID, { 0x8 } }, true, { false } },
// Overwrite the value of TRACE_MARKER_TYPE_CPU_ID with ((uintptr_t)-1).
{ { TRACE_TYPE_MARKER, TRACE_MARKER_TYPE_CPU_ID, { INVALID_CPU_MARKER_VALUE } },
false,
{ true } },
// We need at least one instruction with encodings to make record_filter output
// the trace.
{ { TRACE_TYPE_ENCODING, 3, { ENCODING } }, true, { true } },
{ { TRACE_TYPE_INSTR, 3, { PC } }, true, { true } },

{ { TRACE_TYPE_FOOTER, 0, { 0x0 } }, true, { true } },
};

// Construct modify_marker_value_filter_t. We change TRACE_MARKER_TYPE_CPU_ID values
// with INVALID_CPU_MARKER_VALUE == ((uintptr_t)-1) and TRACE_MARKER_TYPE_PAGE_SIZE
// with 2k.
std::vector<uint64_t> modify_marker_value_pairs_list = { TRACE_MARKER_TYPE_CPU_ID,
INVALID_CPU_MARKER_VALUE,
TRACE_MARKER_TYPE_PAGE_SIZE,
NEW_PAGE_SIZE_MARKER_VALUE };
std::vector<std::unique_ptr<record_filter_func_t>> filters;
auto modify_marker_value_filter = std::unique_ptr<record_filter_func_t>(
new dynamorio::drmemtrace::modify_marker_value_filter_t(
modify_marker_value_pairs_list));
if (!modify_marker_value_filter->get_error_string().empty()) {
fprintf(stderr, "Couldn't construct a modify_marker_value_filter %s",
modify_marker_value_filter->get_error_string().c_str());
return false;
}
filters.push_back(std::move(modify_marker_value_filter));

// Construct record_filter_t.
test_record_filter_t record_filter(std::move(filters), 0, /*write_archive=*/true);

// Run the test.
if (!process_entries_and_check_result(&record_filter, entries, 0))
return false;

fprintf(stderr, "test_modify_marker_value_filter passed\n");
return true;
}

static bool
test_cache_and_type_filter()
{
Expand Down Expand Up @@ -1450,7 +1525,7 @@ test_main(int argc, const char *argv[])
dr_standalone_init();
if (!test_cache_and_type_filter() || !test_chunk_update() || !test_trim_filter() ||
!test_null_filter() || !test_wait_filter() || !test_encodings2regdeps_filter() ||
!test_func_id_filter())
!test_func_id_filter() || !test_modify_marker_value_filter())
return 1;
fprintf(stderr, "All done!\n");
dr_standalone_exit();
Expand Down
Loading

0 comments on commit fa2d07c

Please sign in to comment.