1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef SUB_EVENT_PARSER_H 16 #define SUB_EVENT_PARSER_H 17 #include <cstdint> 18 #include <functional> 19 #include <map> 20 21 #include "ftrace_field_parser.h" 22 #include "logging.h" 23 #include "trace_plugin_result.pb.h" 24 #include "trace_plugin_result.pbencoder.h" 25 26 FTRACE_NS_BEGIN 27 28 template <class T> // T: FtraceEvent 29 class SubEventParser { 30 public: 31 using ParseFunction = std::function<void(T&, uint8_t[], size_t, const EventFormat&)>; 32 struct ParseEventCtx { 33 EventFormat format; 34 ParseFunction func; 35 }; 36 SubEventParser()37 SubEventParser() 38 { 39 PROFILER_LOG_INFO(LOG_CORE, "SubEventParser create!"); 40 } 41 ~SubEventParser()42 ~SubEventParser() 43 { 44 PROFILER_LOG_INFO(LOG_CORE, "SubEventParser destroy!"); 45 } 46 GetInstance()47 static SubEventParser<T>& GetInstance() 48 { 49 static SubEventParser<T> instance; 50 return instance; 51 } 52 IsSupport(const std::string & eventName)53 inline bool IsSupport(const std::string& eventName) const 54 { 55 return nameToFunctions_.count(eventName) > 0; 56 } 57 SetupEvent(const EventFormat & format)58 bool SetupEvent(const EventFormat& format) 59 { 60 auto it = nameToFunctions_.find(format.eventName); 61 if (it == nameToFunctions_.end()) { 62 PROFILER_LOG_INFO(LOG_CORE, "SetupEvent: event(%s) is not supported", format.eventName.c_str()); 63 return false; 64 } 65 66 it->second.format = format; 67 idToParseCtx_[format.eventId] = it->second; 68 69 if (format.eventName == "sched_switch") { 70 schedSwitchCtx = &it->second; 71 schedSwitchEventID = format.eventId; 72 } else if (format.eventName == "sched_waking") { 73 schedWakingCtx = &it->second; 74 schedWakingEventID = format.eventId; 75 } else { 76 idToFunctions_[format.eventId] = &idToParseCtx_[format.eventId]; 77 } 78 return true; 79 } 80 GetParseEventCtx(uint32_t eventId)81 inline ParseEventCtx* GetParseEventCtx(uint32_t eventId) 82 { 83 if (eventId == schedSwitchEventID) { 84 return schedSwitchCtx; 85 } else if (eventId == schedWakingEventID) { 86 return schedWakingCtx; 87 } 88 89 auto it = idToFunctions_.find(eventId); 90 if (it != idToFunctions_.end()) { 91 return it->second; 92 } 93 94 return nullptr; 95 } 96 ParseEvent(T & event,uint8_t data[],size_t size,const ParseEventCtx * parseEventCtx)97 inline void ParseEvent(T& event, 98 uint8_t data[], 99 size_t size, 100 const ParseEventCtx* parseEventCtx) const 101 { 102 parseEventCtx->func(event, data, size, parseEventCtx->format); 103 } 104 105 protected: 106 friend class SubEventParserRegisterar; 107 friend class SubEventParserOptimizeRegisterar; 108 RegisterParseFunction(const std::string & name,ParseFunction && func)109 void RegisterParseFunction(const std::string& name, ParseFunction&& func) 110 { 111 CHECK_TRUE(nameToFunctions_.count(name) == 0, NO_RETVAL, 112 "parse function for %s already registered!", name.c_str()); 113 nameToFunctions_[name] = {{}, func}; 114 } 115 UnregisterParseFunction(const std::string & name)116 void UnregisterParseFunction(const std::string& name) 117 { 118 CHECK_TRUE(nameToFunctions_.count(name) > 0, NO_RETVAL, "parse function for %s not registered!", name.c_str()); 119 nameToFunctions_.erase(name); 120 } 121 122 private: 123 DISALLOW_COPY_AND_MOVE(SubEventParser); 124 std::unordered_map<std::string, ParseEventCtx> nameToFunctions_; 125 std::unordered_map<uint32_t, ParseEventCtx> idToParseCtx_; 126 std::unordered_map<uint32_t, ParseEventCtx*> idToFunctions_; 127 128 uint32_t schedSwitchEventID = (uint32_t)-1; 129 uint32_t schedWakingEventID = (uint32_t)-1; 130 ParseEventCtx* schedSwitchCtx = nullptr; 131 ParseEventCtx* schedWakingCtx = nullptr; 132 }; 133 134 class SubEventParserRegisterar { 135 public: SubEventParserRegisterar(const std::string & name,SubEventParser<FtraceEvent>::ParseFunction && func)136 SubEventParserRegisterar(const std::string& name, SubEventParser<FtraceEvent>::ParseFunction&& func) 137 { 138 SubEventParser<FtraceEvent>::GetInstance().RegisterParseFunction(name, std::move(func)); 139 name_ = name; 140 } ~SubEventParserRegisterar()141 ~SubEventParserRegisterar() 142 { 143 SubEventParser<FtraceEvent>::GetInstance().UnregisterParseFunction(name_); 144 } 145 146 private: 147 DISALLOW_COPY_AND_MOVE(SubEventParserRegisterar); 148 std::string name_; 149 }; 150 151 class SubEventParserOptimizeRegisterar { 152 public: SubEventParserOptimizeRegisterar(const std::string & name,SubEventParser<Developtools::Profiler::ProtoEncoder::FtraceEvent>::ParseFunction && func)153 SubEventParserOptimizeRegisterar(const std::string& name, 154 SubEventParser<Developtools::Profiler::ProtoEncoder::FtraceEvent>::ParseFunction&& func) 155 { 156 SubEventParser<Developtools::Profiler::ProtoEncoder::FtraceEvent>::GetInstance().RegisterParseFunction(name, 157 std::move(func)); 158 name_ = name; 159 } ~SubEventParserOptimizeRegisterar()160 ~SubEventParserOptimizeRegisterar() 161 { 162 SubEventParser<Developtools::Profiler::ProtoEncoder::FtraceEvent>::GetInstance().UnregisterParseFunction(name_); 163 } 164 165 private: 166 DISALLOW_COPY_AND_MOVE(SubEventParserOptimizeRegisterar); 167 std::string name_; 168 }; 169 FTRACE_NS_END 170 171 // Register the protobuf parsing function 172 #define REGISTER_FTRACE_EVENT_PARSE_FUNCTION(name, func) \ 173 static FTRACE_NS::SubEventParserRegisterar g_eventRegisterar##name(#name, func) 174 175 // Register the proto_encoder parsing function 176 #define REGISTER_FTRACE_EVENT_PARSE_ENCODER_FUNCTION(name, func) \ 177 static FTRACE_NS::SubEventParserOptimizeRegisterar g_eventOptimizeRegisterar##name(#name, func) 178 179 #endif // SUB_EVENT_PARSER_H 180