1 /* 2 * Copyright (C) 2018 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_CONFIG_MUXER_H_ 18 #define SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_MUXER_H_ 19 20 #include <map> 21 #include <set> 22 23 #include "src/traced/probes/ftrace/compact_sched.h" 24 #include "src/traced/probes/ftrace/ftrace_config_utils.h" 25 #include "src/traced/probes/ftrace/ftrace_controller.h" 26 #include "src/traced/probes/ftrace/ftrace_procfs.h" 27 #include "src/traced/probes/ftrace/proto_translation_table.h" 28 29 namespace perfetto { 30 31 namespace protos { 32 namespace pbzero { 33 enum FtraceClock : int32_t; 34 } // namespace pbzero 35 } // namespace protos 36 37 struct FtraceSetupErrors; 38 39 // State held by the muxer per data source, used to parse ftrace according to 40 // that data source's config. 41 struct FtraceDataSourceConfig { FtraceDataSourceConfigFtraceDataSourceConfig42 FtraceDataSourceConfig(EventFilter _event_filter, 43 CompactSchedConfig _compact_sched, 44 std::vector<std::string> _atrace_apps, 45 std::vector<std::string> _atrace_categories, 46 bool _symbolize_ksyms) 47 : event_filter(std::move(_event_filter)), 48 compact_sched(_compact_sched), 49 atrace_apps(std::move(_atrace_apps)), 50 atrace_categories(std::move(_atrace_categories)), 51 symbolize_ksyms(_symbolize_ksyms) {} 52 53 // The event filter allows to quickly check if a certain ftrace event with id 54 // x is enabled for this data source. 55 EventFilter event_filter; 56 57 // Configuration of the optional compact encoding of scheduling events. 58 const CompactSchedConfig compact_sched; 59 60 // Used only in Android for ATRACE_EVENT/os.Trace() userspace annotations. 61 std::vector<std::string> atrace_apps; 62 std::vector<std::string> atrace_categories; 63 64 // When enabled will turn on the kallsyms symbolizer in CpuReader. 65 const bool symbolize_ksyms; 66 }; 67 68 // Ftrace is a bunch of globally modifiable persistent state. 69 // Given a number of FtraceConfig's we need to find the best union of all 70 // the settings to make everyone happy while also watching out for anybody 71 // messing with the ftrace settings at the same time as us. 72 // 73 // Specifically FtraceConfigMuxer takes in a *requested* FtraceConfig 74 // (|SetupConfig|), makes a best effort attempt to modify the ftrace 75 // debugfs files to honor those settings without interrupting other perfetto 76 // traces already in progress or other users of ftrace, then returns an 77 // FtraceConfigId representing that config or zero on failure. 78 // 79 // When you are finished with a config you can signal that with |RemoveConfig|. 80 class FtraceConfigMuxer { 81 public: 82 // The FtraceConfigMuxer and ProtoTranslationTable 83 // should outlive this instance. 84 FtraceConfigMuxer( 85 FtraceProcfs* ftrace, 86 ProtoTranslationTable* table, 87 std::map<std::string, std::vector<GroupAndName>> vendor_events); 88 virtual ~FtraceConfigMuxer(); 89 90 // Ask FtraceConfigMuxer to adjust ftrace procfs settings to 91 // match the requested config. Returns an id to manage this 92 // config or zero on failure. 93 // This is best effort. FtraceConfigMuxer may not be able to adjust the 94 // buffer size right now. Events may be missing or there may be extra events 95 // (if you enable an atrace category we try to give you the matching events). 96 // If someone else is tracing we won't touch atrace (since it resets the 97 // buffer). 98 FtraceConfigId SetupConfig(const FtraceConfig& request, 99 FtraceSetupErrors* = nullptr); 100 101 // Activate ftrace for the given config (if not already active). 102 bool ActivateConfig(FtraceConfigId); 103 104 // Undo changes for the given config. Returns false iff the id is 0 105 // or already removed. 106 bool RemoveConfig(FtraceConfigId); 107 108 const FtraceDataSourceConfig* GetDataSourceConfig(FtraceConfigId id); 109 110 // Returns the current per-cpu buffer size, as configured by this muxer 111 // (without consulting debugfs). Constant for a given tracing session. 112 // Note that if there are multiple concurrent tracing sessions, the first 113 // session's buffer size is used for all of them. 114 size_t GetPerCpuBufferSizePages(); 115 116 // public for testing SetupClockForTesting(const FtraceConfig & request)117 void SetupClockForTesting(const FtraceConfig& request) { 118 SetupClock(request); 119 } 120 ftrace_clock()121 protos::pbzero::FtraceClock ftrace_clock() const { 122 return current_state_.ftrace_clock; 123 } 124 GetFtraceEventsForTesting(const FtraceConfig & request,const ProtoTranslationTable * table)125 std::set<GroupAndName> GetFtraceEventsForTesting( 126 const FtraceConfig& request, 127 const ProtoTranslationTable* table) { 128 return GetFtraceEvents(request, table); 129 } 130 GetCentralEventFilterForTesting()131 const EventFilter* GetCentralEventFilterForTesting() const { 132 return ¤t_state_.ftrace_events; 133 } 134 135 private: 136 static bool StartAtrace(const std::vector<std::string>& apps, 137 const std::vector<std::string>& categories, 138 std::string* atrace_errors); 139 140 struct FtraceState { 141 EventFilter ftrace_events; 142 // Used only in Android for ATRACE_EVENT/os.Trace() userspace 143 std::vector<std::string> atrace_apps; 144 std::vector<std::string> atrace_categories; 145 size_t cpu_buffer_size_pages = 0; 146 bool atrace_on = false; 147 protos::pbzero::FtraceClock ftrace_clock{}; 148 }; 149 150 FtraceConfigMuxer(const FtraceConfigMuxer&) = delete; 151 FtraceConfigMuxer& operator=(const FtraceConfigMuxer&) = delete; 152 153 void SetupClock(const FtraceConfig& request); 154 void SetupBufferSize(const FtraceConfig& request); 155 void UpdateAtrace(const FtraceConfig& request, std::string* atrace_errors); 156 void DisableAtrace(); 157 158 // This processes the config to get the exact events. 159 // group/* -> Will read the fs and add all events in group. 160 // event -> Will look up the event to find the group. 161 // atrace category -> Will add events in that category. 162 std::set<GroupAndName> GetFtraceEvents(const FtraceConfig& request, 163 const ProtoTranslationTable*); 164 165 FtraceConfigId GetNextId(); 166 167 FtraceConfigId last_id_ = 1; 168 FtraceProcfs* ftrace_; 169 ProtoTranslationTable* table_; 170 171 FtraceState current_state_; 172 173 // Set of all requested tracing configurations, with the associated derived 174 // data used during parsing. Note that not all of these configurations might 175 // be active. When a config is present but not active, we do setup buffer 176 // sizes and events, but don't enable ftrace (i.e. tracing_on). 177 std::map<FtraceConfigId, FtraceDataSourceConfig> ds_configs_; 178 179 std::map<std::string, std::vector<GroupAndName>> vendor_events_; 180 181 // Subset of |ds_configs_| that are currently active. At any time ftrace is 182 // enabled iff |active_configs_| is not empty. 183 std::set<FtraceConfigId> active_configs_; 184 }; 185 186 size_t ComputeCpuBufferSizeInPages(size_t requested_buffer_size_kb); 187 188 } // namespace perfetto 189 190 #endif // SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_MUXER_H_ 191