/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_FTRACE_READER_FTRACE_CONFIG_MUXER_H_ #define SRC_FTRACE_READER_FTRACE_CONFIG_MUXER_H_ #include "perfetto/ftrace_reader/ftrace_controller.h" #include "src/ftrace_reader/ftrace_procfs.h" namespace perfetto { // Ftrace is a bunch of globaly modifiable persistent state. // Given a number of FtraceConfig's we need to find the best union of all // the settings to make eveyone happy while also watching out for anybody // messing with the ftrace settings at the same time as us. // Specifically FtraceConfigMuxer takes in a *requested* FtraceConfig // (|RequestConfig|), makes a best effort attempt to modify the ftrace // debugfs files to honor those settings without interupting other perfetto // traces already in progress or other users of ftrace, then returns an // FtraceConfigId representing that config or zero on failure. // To see which settings we actually managed to set you can call |GetConfig| // and when you are finished with a config you can signal that with // |RemoveConfig|. class FtraceConfigMuxer { public: // The FtraceConfigMuxer and ProtoTranslationTable // should outlive this instance. FtraceConfigMuxer(FtraceProcfs* ftrace, const ProtoTranslationTable* table); virtual ~FtraceConfigMuxer(); // Ask FtraceConfigMuxer to adjust ftrace procfs settings to // match the requested config. Returns an id to manage this // config or zero on failure. // This is best effort. FtraceConfigMuxer may not be able to adjust the // buffer size right now. Events may be missing or there may be extra events // (if you enable an atrace catagory we try to give you the matching events). // If someone else is tracing we won't touch atrace (since it resets the // buffer). // To see the config you ended up with use |GetConfig|. FtraceConfigId RequestConfig(const FtraceConfig& request); // Undo changes for the given config. Returns false iff the id is 0 // or already removed. bool RemoveConfig(FtraceConfigId id); // public for testing void SetupClockForTesting(const FtraceConfig& request) { SetupClock(request); } const FtraceConfig* GetConfig(FtraceConfigId id); private: struct FtraceState { std::set<std::string> ftrace_events; std::set<std::string> atrace_categories; std::set<std::string> atrace_apps; bool tracing_on = false; bool atrace_on = false; size_t cpu_buffer_size_pages = 0; }; FtraceConfigMuxer(const FtraceConfigMuxer&) = delete; FtraceConfigMuxer& operator=(const FtraceConfigMuxer&) = delete; void SetupClock(const FtraceConfig& request); void SetupBufferSize(const FtraceConfig& request); void UpdateAtrace(const FtraceConfig& request); void DisableAtrace(); FtraceConfigId GetNextId(); FtraceConfigId last_id_ = 1; FtraceProcfs* ftrace_; const ProtoTranslationTable* table_; FtraceState current_state_; std::map<FtraceConfigId, FtraceConfig> configs_; }; std::set<std::string> GetFtraceEvents(const FtraceConfig& request, const ProtoTranslationTable*); size_t ComputeCpuBufferSizeInPages(size_t requested_buffer_size_kb); } // namespace perfetto #endif // SRC_FTRACE_READER_FTRACE_CONFIG_MUXER_H_