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 // Called at the end of trace to flush any events which are pending to the 81 // storage. 82 void FlushPendingEvents(); 83 84 private: 85 // Information retained from the preceding sched_switch seen on a given cpu. 86 struct PendingSchedInfo { 87 // The pending scheduling slice that the next event will complete. 88 uint32_t pending_slice_storage_idx = std::numeric_limits<uint32_t>::max(); 89 90 // pid/utid/prio corresponding to the last sched_switch seen on this cpu 91 // (its "next_*" fields). There is some duplication with respect to the 92 // slices storage, but we don't always have a slice when decoding events in 93 // the compact format. 94 uint32_t last_pid = std::numeric_limits<uint32_t>::max(); 95 UniqueTid last_utid = std::numeric_limits<UniqueTid>::max(); 96 int32_t last_prio = std::numeric_limits<int32_t>::max(); 97 }; 98 99 uint32_t AddRawEventAndStartSlice(uint32_t cpu, 100 int64_t ts, 101 UniqueTid prev_utid, 102 uint32_t prev_pid, 103 StringId prev_comm_id, 104 int32_t prev_prio, 105 int64_t prev_state, 106 UniqueTid next_utid, 107 uint32_t next_pid, 108 StringId next_comm_id, 109 int32_t next_prio); 110 111 void ClosePendingSlice(uint32_t slice_idx, int64_t ts, int64_t prev_state); 112 113 // Infromation retained from the preceding sched_switch seen on a given cpu. 114 std::array<PendingSchedInfo, kMaxCpus> pending_sched_per_cpu_{}; 115 116 static constexpr uint8_t kSchedSwitchMaxFieldId = 7; 117 std::array<StringId, kSchedSwitchMaxFieldId + 1> sched_switch_field_ids_; 118 StringId sched_switch_id_; 119 120 static constexpr uint8_t kSchedWakingMaxFieldId = 5; 121 std::array<StringId, kSchedWakingMaxFieldId + 1> sched_waking_field_ids_; 122 StringId sched_waking_id_; 123 124 TraceProcessorContext* const context_; 125 }; 126 127 } // namespace trace_processor 128 } // namespace perfetto 129 130 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_ 131