trace_processor: invalidate mismatched pid sched slices
Bug: 123330687
Change-Id: Iacf17943e950f12524cff035c762d5bbaacfe780
diff --git a/src/trace_processor/event_tracker.cc b/src/trace_processor/event_tracker.cc
index b51923d..206bf3c 100644
--- a/src/trace_processor/event_tracker.cc
+++ b/src/trace_processor/event_tracker.cc
@@ -68,7 +68,8 @@
idx, ftrace_utils::TaskState(static_cast<uint16_t>(prev_state)));
} else {
// If the this events previous pid does not match the previous event's
- // next pid, make a note of this.
+ // next pid, invalidate the slice and add it to the stats.
+ slices->InvalidateSlice(idx);
context_->storage->IncrementStats(stats::mismatched_sched_switch_tids);
}
}
diff --git a/src/trace_processor/event_tracker_unittest.cc b/src/trace_processor/event_tracker_unittest.cc
index adcb4e8..cb79165 100644
--- a/src/trace_processor/event_tracker_unittest.cc
+++ b/src/trace_processor/event_tracker_unittest.cc
@@ -86,9 +86,9 @@
context.event_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
prev_state,
/*tid=*/2, kCommProc2, next_prio);
- context.event_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/4,
+ context.event_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2,
prev_state,
- /*tid=*/2, kCommProc1, next_prio);
+ /*tid=*/4, kCommProc1, next_prio);
ASSERT_EQ(timestamps.size(), 4ul);
ASSERT_EQ(timestamps[0], timestamp);
@@ -100,6 +100,26 @@
context.storage->slices().utids().at(2));
}
+TEST_F(EventTrackerTest, SchedMismatchedPids) {
+ uint32_t cpu = 3;
+ int64_t timestamp = 100;
+ int64_t prev_state = 32;
+ static const char kCommProc1[] = "process1";
+ static const char kCommProc2[] = "process2";
+ int32_t next_prio = 1024;
+
+ context.event_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
+ prev_state,
+ /*tid=*/4, kCommProc1, next_prio);
+ context.event_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/3,
+ prev_state,
+ /*tid=*/2, kCommProc2, next_prio);
+
+ ASSERT_EQ(context.storage->slices().utids().at(0),
+ std::numeric_limits<UniqueTid>::max());
+ ASSERT_EQ(context.storage->slices().utids().at(0), kInvalidUtid);
+}
+
TEST_F(EventTrackerTest, CounterDuration) {
uint32_t cpu = 3;
int64_t timestamp = 100;
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index 4df9400..da82bf3 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -73,7 +73,7 @@
"where dur != 0 and utid != 0",
&res);
ASSERT_EQ(res.num_records(), 1);
- ASSERT_EQ(res.columns(0).long_values(0), 139789);
+ ASSERT_EQ(res.columns(0).long_values(0), 139792);
ASSERT_EQ(res.columns(1).long_values(0), 19684308497);
}
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 63e34ff..21ad86b 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -17,8 +17,10 @@
#ifndef SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
#define SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
+#include <algorithm>
#include <array>
#include <deque>
+#include <limits>
#include <map>
#include <string>
#include <unordered_map>
@@ -43,6 +45,7 @@
// UniqueTid is an offset into |unique_threads_|. Necessary because tids can
// be reused.
using UniqueTid = uint32_t;
+constexpr UniqueTid kInvalidUtid = std::numeric_limits<UniqueTid>::max();
// StringId is an offset into |string_pool_|.
using StringId = uint32_t;
@@ -192,6 +195,20 @@
return slice_count() - 1;
}
+ void InvalidateSlice(size_t index) {
+ using T = decltype(rows_for_utids_)::value_type;
+ auto pair = rows_for_utids_.equal_range(utids_[index]);
+ auto it = std::find_if(pair.first, pair.second,
+ [index](const T& p) { return index == p.second; });
+ PERFETTO_CHECK(it != pair.second);
+ rows_for_utids_.erase(it);
+
+ utids_[index] = kInvalidUtid;
+ end_states_[index] = ftrace_utils::TaskState();
+ priorities_[index] = 0;
+ rows_for_utids_.emplace(kInvalidUtid, index);
+ }
+
void set_duration(size_t index, int64_t duration_ns) {
durations_[index] = duration_ns;
}