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/ftrace_config.h" 24 #include "src/traced/probes/ftrace/ftrace_controller.h" 25 #include "src/traced/probes/ftrace/ftrace_procfs.h" 26 #include "src/traced/probes/ftrace/proto_translation_table.h" 27 28 namespace perfetto { 29 30 // Ftrace is a bunch of globaly modifiable persistent state. 31 // Given a number of FtraceConfig's we need to find the best union of all 32 // the settings to make eveyone happy while also watching out for anybody 33 // messing with the ftrace settings at the same time as us. 34 35 // Specifically FtraceConfigMuxer takes in a *requested* FtraceConfig 36 // (|SetupConfig|), makes a best effort attempt to modify the ftrace 37 // debugfs files to honor those settings without interupting other perfetto 38 // traces already in progress or other users of ftrace, then returns an 39 // FtraceConfigId representing that config or zero on failure. 40 41 // To see which settings we actually managed to set you can call |GetConfig| 42 // and when you are finished with a config you can signal that with 43 // |RemoveConfig|. 44 class FtraceConfigMuxer { 45 public: 46 // The FtraceConfigMuxer and ProtoTranslationTable 47 // should outlive this instance. 48 FtraceConfigMuxer(FtraceProcfs* ftrace, ProtoTranslationTable* table); 49 virtual ~FtraceConfigMuxer(); 50 51 // Ask FtraceConfigMuxer to adjust ftrace procfs settings to 52 // match the requested config. Returns an id to manage this 53 // config or zero on failure. 54 // This is best effort. FtraceConfigMuxer may not be able to adjust the 55 // buffer size right now. Events may be missing or there may be extra events 56 // (if you enable an atrace catagory we try to give you the matching events). 57 // If someone else is tracing we won't touch atrace (since it resets the 58 // buffer). 59 // To see the config you ended up with use |GetConfig|. 60 FtraceConfigId SetupConfig(const FtraceConfig& request); 61 62 // Activate ftrace for the given config (if not already active). 63 bool ActivateConfig(FtraceConfigId); 64 65 // Undo changes for the given config. Returns false iff the id is 0 66 // or already removed. 67 bool RemoveConfig(FtraceConfigId); 68 69 const EventFilter* GetEventFilter(FtraceConfigId id); 70 71 // public for testing SetupClockForTesting(const FtraceConfig & request)72 void SetupClockForTesting(const FtraceConfig& request) { 73 SetupClock(request); 74 } 75 76 const FtraceConfig* GetConfigForTesting(FtraceConfigId id); 77 GetFtraceEventsForTesting(const FtraceConfig & request,const ProtoTranslationTable * table)78 std::set<GroupAndName> GetFtraceEventsForTesting( 79 const FtraceConfig& request, 80 const ProtoTranslationTable* table) { 81 return GetFtraceEvents(request, table); 82 } 83 84 private: 85 struct FtraceState { 86 EventFilter ftrace_events; 87 std::set<std::string> atrace_categories; 88 std::set<std::string> atrace_apps; 89 bool tracing_on = false; 90 bool atrace_on = false; 91 size_t cpu_buffer_size_pages = 0; 92 }; 93 94 FtraceConfigMuxer(const FtraceConfigMuxer&) = delete; 95 FtraceConfigMuxer& operator=(const FtraceConfigMuxer&) = delete; 96 97 void SetupClock(const FtraceConfig& request); 98 void SetupBufferSize(const FtraceConfig& request); 99 void UpdateAtrace(const FtraceConfig& request); 100 void DisableAtrace(); 101 102 // This processes the config to get the exact events. 103 // group/* -> Will read the fs and add all events in group. 104 // event -> Will look up the event to find the group. 105 // atrace category -> Will add events in that category. 106 std::set<GroupAndName> GetFtraceEvents(const FtraceConfig& request, 107 const ProtoTranslationTable*); 108 109 FtraceConfigId GetNextId(); 110 111 FtraceConfigId last_id_ = 1; 112 FtraceProcfs* ftrace_; 113 ProtoTranslationTable* table_; 114 115 FtraceState current_state_; 116 117 // There is a filter per config. These filters allow a quick way 118 // to check if a certain ftrace event with id x is enabled. 119 std::map<FtraceConfigId, EventFilter> filters_; 120 121 // Set of all configurations. Note that not all of them might be active. 122 // When a config is present but not active, we do setup buffer sizes and 123 // events, but don't enable ftrace (i.e. tracing_on). 124 std::map<FtraceConfigId, FtraceConfig> configs_; 125 126 // Subset of |configs_| that are currently active. At any time ftrace is 127 // enabled iff |active_configs_| is not empty. 128 std::set<FtraceConfigId> active_configs_; 129 }; 130 131 size_t ComputeCpuBufferSizeInPages(size_t requested_buffer_size_kb); 132 133 } // namespace perfetto 134 135 #endif // SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_MUXER_H_ 136