1 /* 2 * Copyright (C) 2017 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_TRACED_PROBES_FTRACE_FTRACE_CONTROLLER_H_ 18 #define SRC_TRACED_PROBES_FTRACE_FTRACE_CONTROLLER_H_ 19 20 #include <stdint.h> 21 #include <unistd.h> 22 23 #include <map> 24 #include <memory> 25 #include <set> 26 #include <string> 27 28 #include "perfetto/base/task_runner.h" 29 #include "perfetto/ext/base/paged_memory.h" 30 #include "perfetto/ext/base/utils.h" 31 #include "perfetto/ext/base/weak_ptr.h" 32 #include "perfetto/ext/tracing/core/basic_types.h" 33 #include "src/traced/probes/ftrace/cpu_reader.h" 34 #include "src/traced/probes/ftrace/ftrace_config_utils.h" 35 36 namespace perfetto { 37 38 class FtraceConfigMuxer; 39 class FtraceDataSource; 40 class FtraceProcfs; 41 class LazyKernelSymbolizer; 42 class ProtoTranslationTable; 43 struct FtraceStats; 44 45 // Method of last resort to reset ftrace state. 46 bool HardResetFtraceState(); 47 48 // Stores the a snapshot of the timestamps from ftrace's trace clock 49 // and CLOCK_BOOTITME. 50 // 51 // This is used when the "boot" (i.e. CLOCK_BOOTITME) is not available 52 // for timestamping trace events (on Android O- and 3.x Linux kernels). 53 // Trace processor can use this data to sync clocks just as it would 54 // with ClockSnapshot packets. 55 struct FtraceClockSnapshot { 56 // The timestamp according to the ftrace clock. 57 int64_t ftrace_clock_ts = 0; 58 59 // The timestamp according to CLOCK_BOOTTIME. 60 int64_t boot_clock_ts = 0; 61 }; 62 63 // Utility class for controlling ftrace. 64 class FtraceController { 65 public: 66 class Observer { 67 public: 68 virtual ~Observer(); 69 virtual void OnFtraceDataWrittenIntoDataSourceBuffers() = 0; 70 }; 71 72 // The passed Observer must outlive the returned FtraceController instance. 73 static std::unique_ptr<FtraceController> Create(base::TaskRunner*, Observer*); 74 virtual ~FtraceController(); 75 76 bool AddDataSource(FtraceDataSource*) PERFETTO_WARN_UNUSED_RESULT; 77 bool StartDataSource(FtraceDataSource*); 78 void RemoveDataSource(FtraceDataSource*); 79 80 // Force a read of the ftrace buffers. Will call OnFtraceFlushComplete() on 81 // all started data sources. 82 void Flush(FlushRequestID); 83 84 void DumpFtraceStats(FtraceDataSource*, FtraceStats*); 85 GetWeakPtr()86 base::WeakPtr<FtraceController> GetWeakPtr() { 87 return weak_factory_.GetWeakPtr(); 88 } 89 90 // public for testing 91 static std::optional<std::string> AbsolutePathForInstance( 92 const std::string& tracefs_root, 93 const std::string& raw_cfg_name); 94 95 protected: 96 // Everything protected/virtual for testing: 97 98 FtraceController(std::unique_ptr<FtraceProcfs>, 99 std::unique_ptr<ProtoTranslationTable>, 100 std::unique_ptr<FtraceConfigMuxer>, 101 base::TaskRunner*, 102 Observer*); 103 104 struct FtraceInstanceState { 105 struct PerCpuState { PerCpuStateFtraceInstanceState::PerCpuState106 PerCpuState(std::unique_ptr<CpuReader> _reader, size_t _period_page_quota) 107 : reader(std::move(_reader)), period_page_quota(_period_page_quota) {} 108 std::unique_ptr<CpuReader> reader; 109 size_t period_page_quota = 0; 110 }; 111 112 FtraceInstanceState(std::unique_ptr<FtraceProcfs>, 113 std::unique_ptr<ProtoTranslationTable>, 114 std::unique_ptr<FtraceConfigMuxer>); 115 116 std::unique_ptr<FtraceProcfs> ftrace_procfs; 117 std::unique_ptr<ProtoTranslationTable> table; 118 std::unique_ptr<FtraceConfigMuxer> ftrace_config_muxer; 119 std::vector<PerCpuState> per_cpu; // empty if no started data sources 120 std::set<FtraceDataSource*> started_data_sources; 121 }; 122 123 FtraceInstanceState* GetInstance(const std::string& instance_name); 124 125 virtual uint64_t NowMs() const; 126 127 // TODO(rsavitski): figure out a better testing shim. 128 virtual std::unique_ptr<FtraceInstanceState> CreateSecondaryInstance( 129 const std::string& instance_name); 130 131 private: 132 friend class TestFtraceController; 133 134 FtraceController(const FtraceController&) = delete; 135 FtraceController& operator=(const FtraceController&) = delete; 136 137 // Periodic task that reads all per-cpu ftrace buffers. 138 void ReadTick(int generation); 139 bool ReadTickForInstance(FtraceInstanceState* instance); 140 uint32_t GetDrainPeriodMs(); 141 142 void FlushForInstance(FtraceInstanceState* instance); 143 144 void StartIfNeeded(FtraceInstanceState* instance); 145 void StopIfNeeded(FtraceInstanceState* instance); 146 147 FtraceInstanceState* GetOrCreateInstance(const std::string& instance_name); 148 void DestroyIfUnusedSeconaryInstance(FtraceInstanceState* instance); 149 150 size_t GetStartedDataSourcesCount() const; 151 void MaybeSnapshotFtraceClock(); // valid only for primary_ tracefs instance 152 153 base::TaskRunner* const task_runner_; 154 Observer* const observer_; 155 base::PagedMemory parsing_mem_; 156 std::unique_ptr<LazyKernelSymbolizer> symbolizer_; 157 FtraceConfigId next_cfg_id_ = 1; 158 int generation_ = 0; 159 bool retain_ksyms_on_stop_ = false; 160 std::set<FtraceDataSource*> data_sources_; 161 // Default tracefs instance (normally /sys/kernel/tracing) is valid for as 162 // long as the controller is valid. 163 // Secondary instances (i.e. /sys/kernel/tracing/instances/...) are created 164 // and destroyed as necessary between AddDataSource and RemoveDataSource: 165 FtraceInstanceState primary_; 166 std::map<std::string, std::unique_ptr<FtraceInstanceState>> 167 secondary_instances_; 168 169 // Additional state for snapshotting non-boot ftrace clock, specific to the 170 // primary_ instance: 171 base::ScopedFile cpu_zero_stats_fd_; 172 std::unique_ptr<FtraceClockSnapshot> ftrace_clock_snapshot_; 173 174 base::WeakPtrFactory<FtraceController> weak_factory_; // Keep last. 175 }; 176 177 } // namespace perfetto 178 179 #endif // SRC_TRACED_PROBES_FTRACE_FTRACE_CONTROLLER_H_ 180