1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_ 19 20 #include <array> 21 #include <limits> 22 23 #include "perfetto/ext/base/string_view.h" 24 #include "perfetto/ext/base/utils.h" 25 #include "src/trace_processor/storage/trace_storage.h" 26 #include "src/trace_processor/types/destructible.h" 27 #include "src/trace_processor/types/trace_processor_context.h" 28 29 namespace perfetto { 30 namespace trace_processor { 31 32 class EventTracker; 33 34 // Tracks sched events and stores them into the storage as sched slices. 35 class SchedEventTracker : public Destructible { 36 public: 37 // Declared public for testing only. 38 explicit SchedEventTracker(TraceProcessorContext*); 39 SchedEventTracker(const SchedEventTracker&) = delete; 40 SchedEventTracker& operator=(const SchedEventTracker&) = delete; 41 ~SchedEventTracker() override; GetOrCreate(TraceProcessorContext * context)42 static SchedEventTracker* GetOrCreate(TraceProcessorContext* context) { 43 if (!context->sched_tracker) { 44 context->sched_tracker.reset(new SchedEventTracker(context)); 45 } 46 return static_cast<SchedEventTracker*>(context->sched_tracker.get()); 47 } 48 49 // This method is called when a sched_switch event is seen in the trace. 50 // Virtual for testing. 51 virtual void PushSchedSwitch(uint32_t cpu, 52 int64_t timestamp, 53 uint32_t prev_pid, 54 base::StringView prev_comm, 55 int32_t prev_prio, 56 int64_t prev_state, 57 uint32_t next_pid, 58 base::StringView next_comm, 59 int32_t next_prio); 60 61 // This method is called when parsing a sched_switch encoded in the compact 62 // format. 63 void PushSchedSwitchCompact(uint32_t cpu, 64 int64_t ts, 65 int64_t prev_state, 66 uint32_t next_pid, 67 int32_t next_prio, 68 StringId next_comm_id); 69 70 // This method is called when parsing a sched_waking encoded in the compact 71 // format. Note that the default encoding is handled by 72 // |EventTracker::PushInstant|. 73 void PushSchedWakingCompact(uint32_t cpu, 74 int64_t ts, 75 uint32_t wakee_pid, 76 int32_t target_cpu, 77 int32_t prio, 78 StringId comm_id); 79 80 private: 81 // Information retained from the preceding sched_switch seen on a given cpu. 82 struct PendingSchedInfo { 83 // The pending scheduling slice that the next event will complete. 84 uint32_t pending_slice_storage_idx = std::numeric_limits<uint32_t>::max(); 85 86 // pid/utid/prio corresponding to the last sched_switch seen on this cpu 87 // (its "next_*" fields). There is some duplication with respect to the 88 // slices storage, but we don't always have a slice when decoding events in 89 // the compact format. 90 uint32_t last_pid = std::numeric_limits<uint32_t>::max(); 91 UniqueTid last_utid = std::numeric_limits<UniqueTid>::max(); 92 int32_t last_prio = std::numeric_limits<int32_t>::max(); 93 }; 94 95 uint32_t AddRawEventAndStartSlice(uint32_t cpu, 96 int64_t ts, 97 UniqueTid prev_utid, 98 uint32_t prev_pid, 99 StringId prev_comm_id, 100 int32_t prev_prio, 101 int64_t prev_state, 102 UniqueTid next_utid, 103 uint32_t next_pid, 104 StringId next_comm_id, 105 int32_t next_prio); 106 107 StringId TaskStateToStringId(int64_t task_state); 108 109 void ClosePendingSlice(uint32_t slice_idx, int64_t ts, StringId prev_state); 110 111 // Information retained from the preceding sched_switch seen on a given cpu. 112 std::vector<PendingSchedInfo> pending_sched_per_cpu_; 113 114 // Get the sched info for the given CPU, resizing the vector if necessary. PendingSchedByCPU(uint32_t cpu)115 PendingSchedInfo* PendingSchedByCPU(uint32_t cpu) { 116 if (PERFETTO_UNLIKELY(cpu >= pending_sched_per_cpu_.size())) { 117 pending_sched_per_cpu_.resize(cpu + 1); 118 } 119 return &pending_sched_per_cpu_[cpu]; 120 } 121 122 static constexpr uint8_t kSchedSwitchMaxFieldId = 7; 123 std::array<StringId, kSchedSwitchMaxFieldId + 1> sched_switch_field_ids_; 124 StringId sched_switch_id_; 125 126 static constexpr uint8_t kSchedWakingMaxFieldId = 5; 127 std::array<StringId, kSchedWakingMaxFieldId + 1> sched_waking_field_ids_; 128 StringId sched_waking_id_; 129 130 StringId waker_utid_id_; 131 132 TraceProcessorContext* const context_; 133 }; 134 135 } // namespace trace_processor 136 } // namespace perfetto 137 138 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_ 139