-
Notifications
You must be signed in to change notification settings - Fork 611
i#7157 dyn inject: Improve ord tracking with synthetic records #7299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
58949b2
c4f2595
f53f9b0
1fbc275
5f682f0
5efb673
e790c3d
3502e28
0521453
e4913f3
6bc5d2c
b16b7c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5770,9 +5770,11 @@ test_unscheduled() | |
| } | ||
|
|
||
| static void | ||
| test_kernel_switch_sequences() | ||
| test_kernel_switch_sequences(bool use_input_ordinals) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my other comment: I don't think we should bother trying to support USE_INPUT_ORDINALS with a dynamic schedule: no known use case wants that. I think we should just disallow it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dynamic schedule and USE_INPUT_ORDINALS seems orthogonal to each other. USE_INPUT_ORDINALS is supposed to affect only what the stream APIs return, not how the scheduler behaves. I don't see why we should disallow that combination.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Even if that is the case, the restriction is not intuitive. Are there other concerns in handling this combination?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This combination is adding complexity and causing extra work with no benefit: better to scope-limit than complicate the code for no benefit. USE_INPUT_ORDINALS was added solely for analyzer use.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I disagree: USE_INPUT_ORDINALS is all about ignoring the output streams and only looking at the inputs; which implies you don't care where the inputs are located -- you don't care about the schedule or whether they are interleaved.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I guess I need to first find some other real case that would hit this need of tracking real/synthetic record count in the queue. I can think of some possible cases but they're harder to write a test for to confirm:
I'll go ahead with #7277 now (which is where I started looking into this issue), because it doesn't look like it is affected: syscall sequences are never injected without seeing an instr on an input, which means the record/instr ordinal over-adjustment gating logic (get_instr_ordinal() == 0) would never be invoked when syscall injected instrs are in the queue. They may be some tricky interaction with instr_pre_read (since syscall injected instrs would also cause it to be decremented) but maybe that's not an issue either because the instr after the syscall would not even be read from the input reader until all syscall injected instrs are done. |
||
| { | ||
| std::cerr << "\n----------------\nTesting kernel switch sequences\n"; | ||
| std::cerr | ||
| << "\n----------------\nTesting kernel switch sequences for use_input_ordinals: " | ||
| << use_input_ordinals << "\n"; | ||
| static constexpr memref_tid_t TID_IN_SWITCHES = 1; | ||
| static constexpr addr_t PROCESS_SWITCH_PC_START = 0xfeed101; | ||
| static constexpr addr_t THREAD_SWITCH_PC_START = 0xcafe101; | ||
|
|
@@ -5838,9 +5840,18 @@ test_kernel_switch_sequences() | |
| } | ||
| sched_inputs.emplace_back(std::move(readers)); | ||
| } | ||
| dynamorio::drmemtrace::scheduler_tmpl_t< | ||
| dynamorio::drmemtrace::_memref_t, | ||
| dynamorio::drmemtrace::reader_t>::scheduler_flags_t flags = | ||
| scheduler_t::SCHEDULER_DEFAULTS; | ||
| if (use_input_ordinals) { | ||
| flags = static_cast<dynamorio::drmemtrace::scheduler_tmpl_t< | ||
| dynamorio::drmemtrace::_memref_t, | ||
| dynamorio::drmemtrace::reader_t>::scheduler_flags_t>( | ||
| flags | scheduler_t::SCHEDULER_USE_INPUT_ORDINALS); | ||
| } | ||
| scheduler_t::scheduler_options_t sched_ops(scheduler_t::MAP_TO_ANY_OUTPUT, | ||
| scheduler_t::DEPENDENCY_TIMESTAMPS, | ||
| scheduler_t::SCHEDULER_DEFAULTS, | ||
| scheduler_t::DEPENDENCY_TIMESTAMPS, flags, | ||
| /*verbosity=*/3); | ||
| sched_ops.quantum_duration_instrs = INSTR_QUANTUM; | ||
| sched_ops.kernel_switch_reader = std::move(switch_reader); | ||
|
|
@@ -5865,6 +5876,7 @@ test_kernel_switch_sequences() | |
| std::vector<bool> in_switch(NUM_OUTPUTS, false); | ||
| std::vector<uint64> prev_in_ord(NUM_OUTPUTS, 0); | ||
| std::vector<uint64> prev_out_ord(NUM_OUTPUTS, 0); | ||
| std::vector<uint64> switch_seq_count(NUM_OUTPUTS, 0); | ||
| while (num_eof < NUM_OUTPUTS) { | ||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | ||
| if (eof[i]) | ||
|
|
@@ -5888,9 +5900,12 @@ test_kernel_switch_sequences() | |
| sched_as_string[i] += | ||
| 'A' + static_cast<char>(memref.instr.tid - TID_BASE); | ||
| } | ||
| bool now_switch = false; | ||
| if (memref.marker.type == TRACE_TYPE_MARKER && | ||
| memref.marker.marker_type == TRACE_MARKER_TYPE_CONTEXT_SWITCH_START) | ||
| memref.marker.marker_type == TRACE_MARKER_TYPE_CONTEXT_SWITCH_START) { | ||
| now_switch = true; | ||
| in_switch[i] = true; | ||
| } | ||
| if (in_switch[i]) { | ||
| // Test that switch code is marked synthetic. | ||
| assert(outputs[i]->is_record_synthetic()); | ||
|
|
@@ -5899,10 +5914,14 @@ test_kernel_switch_sequences() | |
| assert(outputs[i]->get_input_interface()->get_record_ordinal() == | ||
| prev_in_ord[i] || | ||
| // Won't match if we just switched inputs. | ||
| (memref.marker.type == TRACE_TYPE_MARKER && | ||
| memref.marker.marker_type == | ||
| TRACE_MARKER_TYPE_CONTEXT_SWITCH_START)); | ||
| assert(outputs[i]->get_record_ordinal() > prev_out_ord[i]); | ||
| now_switch); | ||
| if (use_input_ordinals) { | ||
| assert(outputs[i]->get_record_ordinal() == prev_out_ord[i] || | ||
| // Won't match if we just switched inputs. | ||
| now_switch); | ||
| } else { | ||
| assert(outputs[i]->get_record_ordinal() > prev_out_ord[i]); | ||
| } | ||
| } else | ||
| assert(!outputs[i]->is_record_synthetic()); | ||
| if (type_is_instr(memref.instr.type)) | ||
|
|
@@ -5912,7 +5931,9 @@ test_kernel_switch_sequences() | |
| case TRACE_MARKER_TYPE_VERSION: sched_as_string[i] += 'v'; break; | ||
| case TRACE_MARKER_TYPE_TIMESTAMP: sched_as_string[i] += '0'; break; | ||
| case TRACE_MARKER_TYPE_CONTEXT_SWITCH_END: | ||
| assert(in_switch[i]); | ||
| in_switch[i] = false; | ||
| ++switch_seq_count[i]; | ||
| ANNOTATE_FALLTHROUGH; | ||
| case TRACE_MARKER_TYPE_CONTEXT_SWITCH_START: | ||
| if (memref.marker.marker_value == scheduler_t::SWITCH_PROCESS) | ||
|
|
@@ -5930,6 +5951,12 @@ test_kernel_switch_sequences() | |
| prev_out_ord[i] = outputs[i]->get_record_ordinal(); | ||
| } | ||
| } | ||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | ||
| assert(switch_seq_count[i] > 0); | ||
| assert(switch_seq_count[i] == | ||
| static_cast<uint64>(outputs[i]->get_schedule_statistic( | ||
| memtrace_stream_t::SCHED_STAT_SWITCH_SEQUENCE_INJECTIONS))); | ||
| } | ||
| // Check the high-level strings. | ||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | ||
| std::cerr << "cpu #" << i << " schedule: " << sched_as_string[i] << "\n"; | ||
|
|
@@ -6730,7 +6757,8 @@ test_main(int argc, const char *argv[]) | |
| test_inactive(); | ||
| test_direct_switch(); | ||
| test_unscheduled(); | ||
| test_kernel_switch_sequences(); | ||
| test_kernel_switch_sequences(/*use_input_ordinals=*/true); | ||
| test_kernel_switch_sequences(/*use_input_ordinals=*/false); | ||
| test_random_schedule(); | ||
| test_record_scheduler(); | ||
| test_rebalancing(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,28 @@ | ||
| Basic counts tool results: | ||
| Schedule stats tool results: | ||
| Total counts: | ||
| [1-9][0-9][0-9][0-9][0-9][0-9] total \(fetched\) instructions | ||
| 5971 total unique \(fetched\) instructions | ||
| [1-9][0-9][0-9][0-9][0-9][0-9] total userspace instructions | ||
| [1-9][0-9][0-9] total kernel instructions | ||
| [1-9][0-9][0-9][0-9][0-9][0-9] total non-fetched instructions | ||
| 4 cores | ||
| .* | ||
| 638960 instructions | ||
| 11 total context switches | ||
| .* | ||
| 6 voluntary context switches | ||
| 0 direct context switches | ||
| 11 context switch sequence injections | ||
| .* | ||
| 9 switches input-to-input | ||
| 5 switches input-to-idle | ||
| 2 switches idle-to-input | ||
| .* | ||
| Core #0 counts: | ||
| .* | ||
| 117031 instructions | ||
| 8 total context switches | ||
| .* | ||
| 3 voluntary context switches | ||
| 0 direct context switches | ||
| 8 context switch sequence injections | ||
| .* | ||
| 6 switches input-to-input | ||
| 3 switches input-to-idle | ||
| 2 switches idle-to-input | ||
| .* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an initial value. Ditto for line 210 (I think it's set in the code before read so no current bug I don't think, but safest to have an initial value).