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;
     }