1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 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 HIPERF_PERF_EVENTS_H 16 #define HIPERF_PERF_EVENTS_H 17 18 #include <atomic> 19 #include <cassert> 20 #include <chrono> 21 #include <cinttypes> 22 #include <condition_variable> 23 #include <deque> 24 #include <map> 25 #include <memory> 26 #include <string> 27 #include <thread> 28 #include <variant> 29 #include <vector> 30 #if !is_mingw 31 #include <poll.h> 32 #endif 33 34 #include <sys/types.h> 35 #include <unique_fd.h> 36 #include <linux/perf_event.h> 37 38 #include "debug_logger.h" 39 #include "perf_event_record.h" 40 #include "perf_record_format.h" 41 #include "ring_buffer.h" 42 #include "tracked_command.h" 43 #include "utilities.h" 44 #include "virtual_runtime.h" 45 46 // this for some performance debug 47 #define HIDEBUG_SKIP_CALLBACK 0 48 #define CALC_OFFSET(offset, size) ((offset) & ((size) - 1)) 49 #ifndef CLOCK_MONOTONIC_RAW 50 #define CLOCK_MONOTONIC_RAW 4 51 #endif 52 #define PERF_AUXTRACE_RECORD_ALIGNMENT 8 53 #define PTR_TO_VOID(ptr) ((void *)(uintptr_t)(ptr)) 54 #define PTR_ADD(b, o) ({ \ 55 uintptr_t _b = (uintptr_t)(b); \ 56 uintptr_t _p = (uintptr_t)&(((uint8_t *)(_b))[o]); \ 57 PTR_TO_VOID(_p); \ 58 }) 59 60 namespace OHOS { 61 namespace Developtools { 62 namespace HiPerf { 63 using ConfigTable = std::map<__u64, const std::string>; 64 using SharedConfigTable = std::unique_ptr<ConfigTable>; 65 66 const std::string PERF_DISABLE_PARAM = "security.perf_harden"; 67 68 // define convert from linux/perf_event.h 69 // description from https://man7.org/linux/man-pages/man2/perf_event_open.2.html 70 71 const ConfigTable PERF_HW_CONFIGS = { 72 {PERF_COUNT_HW_CPU_CYCLES, "hw-cpu-cycles"}, 73 {PERF_COUNT_HW_INSTRUCTIONS, "hw-instructions"}, 74 {PERF_COUNT_HW_CACHE_REFERENCES, "hw-cache-references"}, 75 {PERF_COUNT_HW_CACHE_MISSES, "hw-cache-misses"}, 76 {PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "hw-branch-instructions"}, 77 {PERF_COUNT_HW_BRANCH_MISSES, "hw-branch-misses"}, 78 {PERF_COUNT_HW_BUS_CYCLES, "hw-bus-cycles"}, 79 {PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, "hw-stalled-cycles-frontend"}, 80 {PERF_COUNT_HW_STALLED_CYCLES_BACKEND, "hw-stalled-cycles-backend"}, 81 {PERF_COUNT_HW_REF_CPU_CYCLES, "hw-ref-cpu-cycles"}, 82 }; 83 const ConfigTable PERF_HW_CACHE_CONFIGS = { 84 {PERF_COUNT_HW_CACHE_L1D, "hw-cache-l1d"}, {PERF_COUNT_HW_CACHE_L1I, "hw-cache-l1i"}, 85 {PERF_COUNT_HW_CACHE_LL, "hw-cache-ll"}, {PERF_COUNT_HW_CACHE_DTLB, "hw-cache-dtlb"}, 86 {PERF_COUNT_HW_CACHE_ITLB, "hw-cache-itlb"}, {PERF_COUNT_HW_CACHE_BPU, "hw-cache-bpu"}, 87 {PERF_COUNT_HW_CACHE_NODE, "hw-cache-node"}, 88 }; 89 const ConfigTable PERF_HW_CACHE_OP_CONFIGS = { 90 {PERF_COUNT_HW_CACHE_OP_READ, "hw-cache-op-read"}, 91 {PERF_COUNT_HW_CACHE_OP_WRITE, "hw-cache-op-write"}, 92 {PERF_COUNT_HW_CACHE_OP_PREFETCH, "hw-cache-op-prefetch"}, 93 }; 94 const ConfigTable PERF_HW_CACHE_OP_RESULT_CONFIGS = { 95 {PERF_COUNT_HW_CACHE_RESULT_ACCESS, "hw-cache-result-access"}, 96 {PERF_COUNT_HW_CACHE_RESULT_MISS, "hw-cache-result-miss"}, 97 }; 98 const ConfigTable PERF_SW_CONFIGS = { 99 {PERF_COUNT_SW_CPU_CLOCK, "sw-cpu-clock"}, 100 {PERF_COUNT_SW_TASK_CLOCK, "sw-task-clock"}, 101 {PERF_COUNT_SW_PAGE_FAULTS, "sw-page-faults"}, 102 {PERF_COUNT_SW_CONTEXT_SWITCHES, "sw-context-switches"}, 103 {PERF_COUNT_SW_CPU_MIGRATIONS, "sw-cpu-migrations"}, 104 {PERF_COUNT_SW_PAGE_FAULTS_MIN, "sw-page-faults-min"}, 105 {PERF_COUNT_SW_PAGE_FAULTS_MAJ, "sw-page-faults-maj"}, 106 {PERF_COUNT_SW_ALIGNMENT_FAULTS, "sw-alignment-faults"}, 107 {PERF_COUNT_SW_EMULATION_FAULTS, "sw-emulation-faults"}, 108 {PERF_COUNT_SW_DUMMY, "sw-dummy"}, 109 {PERF_COUNT_SW_BPF_OUTPUT, "sw-bpf-output"}, 110 }; 111 const ConfigTable PERF_RAW_CONFIGS = { 112 {0x0, "raw-sw-incr"}, 113 {0x1, "raw-l1-icache-refill"}, 114 {0x2, "raw-l1-itlb-refill"}, 115 {0x3, "raw-l1-dcache-refill"}, 116 {0x4, "raw-l1-dcache"}, 117 {0x5, "raw-l1-dtlb-refill"}, 118 {0x6, "raw-load-retired"}, 119 {0x7, "raw-store-retired"}, 120 {0x8, "raw-instruction-retired"}, 121 {0x9, "raw-exception-taken"}, 122 {0xa, "raw-exception-return"}, 123 {0xb, "raw-cid-write-retired"}, 124 {0xc, "raw-pc-write-retired"}, 125 {0xd, "raw-br-immed-retired"}, 126 {0xe, "raw-br-return-retired"}, 127 {0xf, "raw-unaligned-ldst-retired"}, 128 {0x10, "raw-br-mis-pred"}, 129 {0x11, "raw-cpu-cycles"}, 130 {0x12, "raw-br-pred"}, 131 {0x13, "raw-mem-access"}, 132 {0x14, "raw-l1-icache"}, 133 {0x15, "raw-l1-dcache-wb"}, 134 {0x16, "raw-l2-dcache"}, 135 {0x17, "raw-l2-dcache-refill"}, 136 {0x18, "raw-l2-dcache-wb"}, 137 {0x19, "raw-bus-access"}, 138 {0x1a, "raw-memory-error"}, 139 {0x1b, "raw-inst-spec"}, 140 {0x1c, "raw-ttbr-write-retired"}, 141 {0x1d, "raw-bus-cycles"}, 142 {0x1f, "raw-l1-dcache-allocate"}, 143 {0x20, "raw-l2-dcache-allocate"}, 144 {0x21, "raw-br-retired"}, 145 {0x22, "raw-br-mis-pred-retired"}, 146 {0x23, "raw-stall-frontend"}, 147 {0x24, "raw-stall-backend"}, 148 {0x25, "raw-l1-dtlb"}, 149 {0x26, "raw-l1-itlb"}, 150 {0x27, "raw-l2-icache"}, 151 {0x28, "raw-l2-icache-refill"}, 152 {0x29, "raw-l3-dcache-allocate"}, 153 {0x2a, "raw-l3-dcache-refill"}, 154 {0x2b, "raw-l3-dcache"}, 155 {0x2c, "raw-l3-dcache-wb"}, 156 {0x2d, "raw-l2-dtlb-refill"}, 157 {0x2e, "raw-l2-itlb-refill"}, 158 {0x2f, "raw-l2-dtlb"}, 159 {0x30, "raw-l2-itlb"}, 160 // newadd 161 {0x31, "raw-remote-access"}, 162 {0x32, "raw-ll-cache"}, 163 {0x33, "raw-ll-cache-miss"}, 164 {0x34, "raw-dtlb-walk"}, 165 {0x35, "raw-itlb-walk"}, 166 {0x36, "raw-ll-cache-rd"}, 167 {0x37, "raw-ll-cache-miss-rd"}, 168 {0x38, "raw-remote-access-rd"}, 169 {0x39, "raw-l1d-cache-lmiss-rd"}, 170 {0x3A, "raw-op-retired"}, 171 {0x3B, "raw-op-spec"}, 172 {0x3C, "raw-stall"}, 173 {0x3D, "raw-stall-slot-backend"}, 174 {0x3E, "raw-stall-slot-frontend"}, 175 {0x3F, "raw-stall-slot"}, 176 {0x40, "raw-l1d-cache-rd"}, 177 {0x4000, "raw-sample-pop"}, 178 {0x4001, "raw-sample-feed"}, 179 {0x4002, "raw-sample-filtrate"}, 180 {0x4003, "raw-sample-collision"}, 181 {0x4004, "raw-cnt-cycles"}, 182 {0x4005, "raw-stall-backend-mem"}, 183 {0x4006, "raw-l1i-cache-lmiss"}, 184 {0x4009, "raw-l2d-cache-lmiss-rd"}, 185 {0x400A, "raw-l2i-cache-lmiss"}, 186 {0x400B, "raw-l3d-cache-lmiss-rd"}, 187 {0x8002, "raw-sve-inst-retired"}, 188 {0x8006, "raw-sve-inst-spec"}, 189 // Refer to "Table K3.1 ARM recommendations for IMPLEMENTATION DEFINED event numbers" in ARMv8 sp 190 {0x0040, "raw-l1d-cache-rd"}, 191 {0x0041, "raw-l1d-cache-wr"}, 192 {0x0042, "raw-l1d-cache-refill-rd"}, 193 {0x0043, "raw-l1d-cache-refill-wr"}, 194 {0x0044, "raw-l1d-cache-refill-inner"}, 195 {0x0045, "raw-l1d-cache-refill-outer"}, 196 {0x0046, "raw-l1d-cache-wb-victim"}, 197 {0x0047, "raw-l1d-cache-wb-clean"}, 198 {0x0048, "raw-l1d-cache-inval"}, 199 // 0x0049-0x004B - Reserved 200 {0x004C, "raw-l1d-tlb-refill-rd"}, 201 {0x004D, "raw-l1d-tlb-refill-wr"}, 202 {0x004E, "raw-l1d-tlb-rd"}, 203 {0x004F, "raw-l1d-tlb-wr"}, 204 {0x0050, "raw-l2d-cache-rd"}, 205 {0x0051, "raw-l2d-cache-wr"}, 206 {0x0052, "raw-l2d-cache-refill-rd"}, 207 {0x0053, "raw-l2d-cache-refill-wr"}, 208 // 0x0054-0x0055 - Reserved 209 {0x0056, "raw-l2d-cache-wb-victim"}, 210 {0x0057, "raw-l2d-cache-wb-clean"}, 211 {0x0058, "raw-l2d-cache-inval"}, 212 // 0x0059-0x005B - Reserved 213 {0x005C, "raw-l2d-tlb-refill-rd"}, 214 {0x005D, "raw-l2d-tlb-refill-wr"}, 215 {0x005E, "raw-l2d-tlb-rd"}, 216 {0x005F, "raw-l2d-tlb-wr"}, 217 {0x0060, "raw-bus-access-rd"}, 218 {0x0061, "raw-bus-access-wr"}, 219 {0x0062, "raw-bus-access-shared"}, 220 {0x0063, "raw-bus-access-not-shared"}, 221 {0x0064, "raw-bus-access-normal"}, 222 {0x0065, "raw-bus-access-periph"}, 223 {0x0066, "raw-mem-access-rd"}, 224 {0x0067, "raw-mem-access-wr"}, 225 {0x0068, "raw-unaligned-ld-spec"}, 226 {0x0069, "raw-unaligned-st-spec"}, 227 {0x006A, "raw-unaligned-ldst-spec"}, 228 // 0x006B - Reserved 229 {0x006C, "raw-ldrex-spec"}, 230 {0x006D, "raw-strex-pass-spec"}, 231 {0x006E, "raw-strex-fail-spec"}, 232 {0x006F, "raw-strex-spec"}, 233 {0x0070, "raw-ld-spec"}, 234 {0x0071, "raw-st-spec"}, 235 {0x0072, "raw-ldst-spec"}, 236 {0x0073, "raw-dp-spec"}, 237 {0x0074, "raw-ase-spec"}, 238 {0x0075, "raw-vfp-spec"}, 239 {0x0076, "raw-pc-write-spec"}, 240 {0x0077, "raw-crypto-spec"}, 241 {0x0078, "raw-br-immed-spec"}, 242 {0x0079, "raw-br-return-spec"}, 243 {0x007A, "raw-br-indirect-spec"}, 244 // 0x007B - Reserved 245 {0x007C, "raw-isb-spec"}, 246 {0x007D, "raw-dsb-spec"}, 247 {0x007E, "raw-dmb-spec"}, 248 // 0x007F-0x0080 - Reserved 249 {0x0081, "raw-exc-undef"}, 250 {0x0082, "raw-exc-svc"}, 251 {0x0083, "raw-exc-pabort"}, 252 {0x0084, "raw-exc-dabort"}, 253 // 0x0085 - Reserved 254 {0x0086, "raw-exc-irq"}, 255 {0x0087, "raw-exc-fiq"}, 256 {0x0088, "raw-exc-smc"}, 257 // 0x0089 - Reserved 258 {0x008A, "raw-exc-hvc"}, 259 {0x008B, "raw-exc-trap-pabort"}, 260 {0x008C, "raw-exc-trap-dabort"}, 261 {0x008D, "raw-exc-trap-other"}, 262 {0x008E, "raw-exc-trap-irq"}, 263 {0x008F, "raw-exc-trap-fiq"}, 264 {0x0090, "raw-rc-ld-spec"}, 265 {0x0091, "raw-rc-st-spec"}, 266 // 0x0092-0x009F - Reserved 267 {0x00A0, "raw-l3d-cache-rd"}, 268 {0x00A1, "raw-l3d-cache-wr"}, 269 {0x00A2, "raw-l3d-cache-refill-rd"}, 270 {0x00A3, "raw-l3d-cache-refill-wr"}, 271 // 0x00A4-0x00A5 - Reserved 272 {0x00A6, "raw-l3d-cache-wb-victim"}, 273 {0x00A7, "raw-l3d-cache-wb-clean"}, 274 {0x00A8, "raw-l3d-cache-inval"}, 275 }; 276 static ConfigTable PERF_TRACEPOINT_CONFIGS = { 277 278 }; 279 280 const std::map<perf_type_id, std::string> PERF_TYPES = { 281 {PERF_TYPE_HARDWARE, "hardware"}, 282 {PERF_TYPE_SOFTWARE, "software"}, 283 {PERF_TYPE_TRACEPOINT, "tracepoint"}, 284 {PERF_TYPE_HW_CACHE, "hardware cache"}, 285 {PERF_TYPE_RAW, "raw"}, 286 }; 287 288 static std::map<perf_type_id, ConfigTable> TYPE_CONFIGS = { 289 {PERF_TYPE_HARDWARE, (PERF_HW_CONFIGS)}, {PERF_TYPE_SOFTWARE, (PERF_SW_CONFIGS)}, 290 {PERF_TYPE_HW_CACHE, (PERF_HW_CACHE_CONFIGS)}, {PERF_TYPE_RAW, (PERF_RAW_CONFIGS)}, 291 {PERF_TYPE_TRACEPOINT, (PERF_TRACEPOINT_CONFIGS)}, 292 }; 293 294 // default config 295 const std::vector<__u64> DEFAULT_HW_CONFIGS = { 296 PERF_COUNT_HW_CPU_CYCLES, 297 #if defined(__aarch64__) 298 PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, 299 PERF_COUNT_HW_STALLED_CYCLES_BACKEND, 300 #endif 301 PERF_COUNT_HW_INSTRUCTIONS, 302 PERF_COUNT_HW_BRANCH_INSTRUCTIONS, 303 PERF_COUNT_HW_BRANCH_MISSES, 304 }; 305 const std::vector<__u64> DEFAULT_SW_CONFIGS = { 306 PERF_COUNT_SW_TASK_CLOCK, 307 PERF_COUNT_SW_CONTEXT_SWITCHES, 308 PERF_COUNT_SW_PAGE_FAULTS, 309 }; 310 const std::map<perf_type_id, std::vector<__u64>> DEFAULT_TYPE_CONFIGS = { 311 {PERF_TYPE_HARDWARE, DEFAULT_HW_CONFIGS}, 312 {PERF_TYPE_SOFTWARE, DEFAULT_SW_CONFIGS}, 313 }; 314 315 struct read_format_event { 316 __u64 value; /* The value of the event */ 317 __u64 id; /* if PERF_FORMAT_ID */ 318 }; 319 320 struct read_format_group { 321 __u64 nr; /* The number of events */ 322 __u64 timeEnabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ 323 __u64 timeRunning; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ 324 read_format_event events[1]; 325 }; 326 327 struct read_format_no_group { 328 __u64 value; /* The value of the event */ 329 __u64 timeEnabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ 330 __u64 timeRunning; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ 331 __u64 id; /* if PERF_FORMAT_ID */ 332 }; 333 334 u32 GetSpeType(); 335 336 class PerfEvents { 337 public: 338 static constexpr uint64_t DEFAULT_SAMPLE_FREQUNCY = 4000; 339 static constexpr uint64_t DEFAULT_SAMPLE_PERIOD = 1; 340 static constexpr uint64_t DEFAULT_TIMEOUT = 10 * 1000; 341 static constexpr size_t MIN_BUFFER_SIZE = 64 * 1024 * 1024; 342 static constexpr size_t BUFFER_LOW_LEVEL = 10 * 1024 * 1024; 343 static constexpr size_t BUFFER_CRITICAL_LEVEL = 5 * 1024 * 1024; 344 static constexpr size_t MAX_BUFFER_SIZE_LITTLE = 128 * 1024 * 1024; 345 static constexpr size_t MAX_BUFFER_SIZE_LARGE = 256 * 1024 * 1024; 346 static constexpr uint64_t DEFAULT_EVENT_MAX_SAMPLE_RATE = 8000; 347 static constexpr uint64_t MIN_HM_TRACEPOINT_EVENT_ID = 32768; 348 static constexpr size_t MAX_HEX_EVENT_NAME_LENGTH = 10; 349 350 PerfEvents(); 351 ~PerfEvents(); 352 353 bool AddEvents(const std::vector<std::string> &eventStrings, const bool group = false); 354 bool PrepareTracking(void); 355 bool StartTracking(const bool immediately = true); 356 bool StopTracking(void); 357 bool PauseTracking(void); 358 bool ResumeTracking(void); 359 bool OutputTracking(); 360 /* call sequence 361 1. setXXX 362 2. AddEvents() 363 3. PrepareTracking 364 4. StartTracking (blocking...) 365 */ 366 bool EnableTracking(); 367 bool IsTrackRunning(); 368 bool IsOutputTracking(); 369 void SetOutputTrackingStatus(const bool status); 370 371 void SetSystemTarget(const bool systemTarget); 372 void SetCpu(const std::vector<pid_t> cpus); // cpu id must be [0~N] 373 void SetPid(const std::vector<pid_t> pids); // tis is same as pid in kernel 374 void SetTimeOut(const float timeOut); 375 void SetTimeReport(int); 376 void SetVerboseReport(const bool); 377 bool AddOffCpuEvent(); 378 SetTrackedCommand(const std::vector<std::string> & trackedCommand)379 inline void SetTrackedCommand(const std::vector<std::string> &trackedCommand) 380 { 381 if (!trackedCommand.empty()) { 382 trackedCommand_ = TrackedCommand::CreateInstance(trackedCommand); 383 } 384 } 385 386 void SetSampleFrequency(const unsigned int frequency); 387 void SetSamplePeriod(const unsigned int period); 388 389 // for background track 390 void SetBackTrack(const bool backtrack); 391 void SetBackTrackTime(const uint64_t backtrackTime); 392 393 enum SampleStackType { 394 NONE, 395 FP, 396 DWARF, 397 }; 398 void SetSampleStackType(const SampleStackType type); 399 void SetDwarfSampleStackSize(const uint32_t stackSize); 400 void SetMmapPages(const size_t mmapPages); 401 std::vector<AttrWithId> GetAttrWithId() const; 402 SetInherit(const bool inherit)403 void SetInherit(const bool inherit) 404 { 405 inherit_ = inherit; 406 }; SetClockId(const int clockId)407 void SetClockId(const int clockId) 408 { 409 clockId_ = clockId; 410 }; 411 void SetPerCpu(const bool perCpu); 412 void SetPerThread(const bool perThread); 413 bool SetBranchSampleType(const uint64_t value); 414 bool AddDefaultEvent(const perf_type_id type); 415 416 std::map<__u64, std::string> GetSupportEvents(const perf_type_id type); 417 418 struct Summary { 419 int cpu = -1; 420 pid_t tid = -1; 421 __u64 eventCount = 0; 422 __u64 timeEnabled = 0; 423 __u64 timeRunning = 0; SummarySummary424 Summary(const int cpu, const pid_t tid, const __u64 eventCount, 425 const __u64 timeEnabled, const __u64 timeRunning) 426 : cpu(cpu), tid(tid), eventCount(eventCount), timeEnabled(timeEnabled), timeRunning(timeRunning) 427 { 428 } 429 }; 430 431 struct ReportSum { 432 int cpu = -1; 433 pid_t pid = -1; 434 pid_t tid = -1; 435 double scaleSum = 1.0; 436 double commentSum = 0; 437 __u64 eventCountSum = 0; 438 __u64 enabledSum = 0; 439 __u64 runningSum = 0; 440 std::string configName = ""; 441 std::string threadName = ""; 442 }; 443 struct CountEvent { 444 bool userOnly = false; 445 bool kernelOnly = false; 446 __u64 eventCount = 0; 447 __u64 timeEnabled = 0; 448 __u64 timeRunning = 0; 449 __u64 id = 0; 450 double usedCpus = 0; 451 std::vector<Summary> summaries; 452 }; 453 using StatCallBack = 454 std::function<void(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &, FILE*)>; 455 using RecordCallBack = std::function<bool(PerfEventRecord&)>; 456 457 void SetStatCallBack(const StatCallBack reportCallBack); 458 void SetRecordCallBack(const RecordCallBack recordCallBack); 459 void SetStatReportFd(FILE* reportPtr); GetLostSamples(size_t & lostSamples,size_t & lostNonSamples)460 void GetLostSamples(size_t &lostSamples, size_t &lostNonSamples) 461 { 462 lostSamples = lostSamples_; 463 lostNonSamples = lostNonSamples_; 464 } 465 466 // review: remove this function. GetStaticConfigName(const perf_type_id type_id,const __u64 config_id)467 static const std::string GetStaticConfigName(const perf_type_id type_id, const __u64 config_id) 468 { 469 auto typeConfigs = TYPE_CONFIGS.find(type_id); 470 if (typeConfigs != TYPE_CONFIGS.end()) { 471 auto configs = typeConfigs->second; 472 auto config = configs.find(config_id); 473 if (config != configs.end()) { 474 return config->second; 475 } else { 476 HLOGW("config not found for %u:%lld in %zu:%zu", type_id, config_id, 477 TYPE_CONFIGS.size(), configs.size()); 478 // dump all config size 479 for (auto types : TYPE_CONFIGS) { 480 HLOGV("type id %d %zu", types.first, types.second.size()); 481 } 482 } 483 } else { 484 HLOGW("type not found for %d in %zu", type_id, TYPE_CONFIGS.size()); 485 } 486 std::string configName = StringPrintf("0x%llx", config_id); 487 return configName; 488 }; 489 GetStaticConfigId(const std::string & event_name)490 static const std::tuple<bool, perf_type_id, __u64> GetStaticConfigId(const std::string &event_name) 491 { 492 for (auto type : TYPE_CONFIGS) { 493 for (auto config : (type.second)) { 494 if (config.second == event_name) { 495 return std::make_tuple(true, type.first, config.first); 496 } 497 } 498 } 499 return std::make_tuple(false, PERF_TYPE_MAX, 0); 500 }; 501 GetTraceConfigName(const __u64 config_id)502 const std::string GetTraceConfigName(const __u64 config_id) 503 { 504 auto config = traceConfigTable.find(config_id); 505 if (config != traceConfigTable.end()) { 506 return config->second; 507 } else { 508 HLOGW("config not found for %lld in traceConfigTable.", config_id); 509 } 510 return "<not found>"; 511 }; 512 513 static const std::string GetTypeName(const perf_type_id type_id); 514 bool ParseEventName(const std::string &nameStr, std::string &name, bool &excludeUser, 515 bool &excludeKernel, bool &isTracePoint); 516 517 // mmap one fd for each cpu 518 struct MmapFd { 519 int fd = -1; 520 perf_event_mmap_page *mmapPage = nullptr; 521 uint8_t *buf = nullptr; 522 size_t bufSize = 0; 523 size_t auxBufSize = 0; 524 // for read and sort 525 size_t dataSize = 0; 526 perf_event_header header; 527 uint64_t timestamp = 0; 528 const perf_event_attr *attr = nullptr; 529 size_t posCallChain = 0; 530 int cpu = -1; 531 void *auxBuf = nullptr; 532 pid_t tid_ = -1; 533 }; 534 535 bool isHM_ = false; 536 bool isSpe_ = false; 537 538 void SetHM(const bool isHM); 539 void SetConfig(std::map<const std::string, uint64_t> &speOptMaps); 540 private: 541 size_t recordEventCount_ = 0; // only for debug time 542 #ifdef HIPERF_DEBUG_TIME 543 std::chrono::microseconds recordCallBackTime_ = std::chrono::microseconds::zero(); 544 std::chrono::microseconds recordWaitDataTime_ = std::chrono::microseconds::zero(); 545 std::chrono::microseconds recordSleepTime_ = std::chrono::microseconds::zero(); 546 std::chrono::microseconds recordKernelReadTime_ = std::chrono::microseconds::zero(); 547 #endif 548 size_t lostSamples_ = 0; 549 size_t lostNonSamples_ = 0; 550 551 std::unique_ptr<RingBuffer> recordBuf_ {nullptr}; 552 bool recordBufReady_ = false; 553 std::mutex mtxRrecordBuf_; 554 std::condition_variable cvRecordBuf_; 555 std::thread readRecordBufThread_; 556 std::atomic_bool readRecordThreadRunning_ = false; 557 bool startedTracking_ = false; 558 bool isLowPriorityThread_ = false; 559 void RecordLoop(); 560 void StatLoop(); 561 bool IsRecordInMmap(const int timeout); 562 void ReadRecordsFromMmaps(); 563 void ReadRecordsFromSpeMmaps(MmapFd& mmapFd, const u64 auxOffset, u64 auxSize, const u32 pid, const u32 tid); 564 void SpeReadData(void *dataPage, u64 *dataTail, uint8_t *buf, const u32 size); 565 bool GetRecordFromMmap(MmapFd &mmap); 566 void GetRecordFieldFromMmap(MmapFd &mmap, void *dest, size_t pos, size_t size); 567 void MoveRecordToBuf(MmapFd &mmap, bool &isAuxEvent, u64 &auxOffset, u64 &auxSize, u32 &pid, u32 &tid); 568 size_t GetCallChainPosInSampleRecord(const perf_event_attr &attr); 569 size_t GetStackSizePosInSampleRecord(MmapFd &mmap); 570 bool CutStackAndMove(MmapFd &mmap); 571 inline void WaitDataFromRingBuffer(); 572 inline bool ProcessRecord(const perf_event_attr* attr, uint8_t* data); 573 void ReadRecordFromBuf(); 574 size_t CalcBufferSize(); 575 bool PrepareRecordThread(); 576 void WaitRecordThread(); 577 bool HaveTargetsExit(const std::chrono::steady_clock::time_point &startTime); 578 void ExitReadRecordBufThread(); 579 580 #ifdef CONFIG_HAS_CCM 581 static constexpr char PRODUCT_CONFIG_PATH[] = "etc/hiperf/hiperf_cfg.json"; 582 static constexpr char CFG_MAX_BUFFER_SIZE[] = "MaxBufferSize"; 583 static constexpr char CFG_MIN_BUFFER_SIZE[] = "MinBufferSize"; 584 void GetBufferSizeCfg(size_t &maxBufferSize, size_t &minBufferSize); 585 #endif 586 587 enum EventSpaceType { 588 UNKNOW = 0, 589 USER = 1, 590 KERNEL = 2, 591 USER_KERNEL = 3, 592 }; 593 uint8_t eventSpaceType_ = EventSpaceType::UNKNOW; 594 595 bool inherit_ = false; 596 std::vector<pid_t> pids_; 597 std::vector<pid_t> cpus_; 598 std::vector<OHOS::UniqueFd> groups_; 599 std::chrono::milliseconds timeOut_; // milliseconds 600 std::chrono::milliseconds timeReport_; // means same as timeOut 601 bool perCpu_ = false; 602 bool perThread_ = false; 603 bool verboseReport_ = false; 604 bool prepared_ = false; 605 ConfigTable traceConfigTable; 606 607 unsigned int samplePeriod_ = 0; 608 unsigned int sampleFreq_ = 0; 609 uint64_t config_ = 0; 610 uint64_t config1_ = 0; 611 uint64_t config2_ = 0; 612 unsigned int speType_ = 0; 613 614 struct FdItem { 615 OHOS::UniqueFd fd; 616 int cpu = -1; 617 pid_t pid = -1; 618 pid_t tid = -1; 619 __u64 eventCount = 0; 620 mutable uint64_t perfId = 0; GetPrefIdFdItem621 uint64_t GetPrefId() const 622 { 623 if (perfId == 0) { 624 read_format_no_group readNoGroupValue; 625 if (read(fd, &readNoGroupValue, sizeof(readNoGroupValue)) > 0) { 626 perfId = readNoGroupValue.id; 627 } else { 628 HLOGW("read failed with fd %d", fd.Get()); 629 } 630 } 631 return perfId; 632 } 633 }; 634 struct EventItem { 635 std::string typeName; 636 std::string configName; 637 perf_event_attr attr = {}; 638 std::vector<FdItem> fdItems; 639 }; 640 struct EventGroupItem { 641 std::vector<EventItem> eventItems; 642 }; 643 std::vector<EventGroupItem> eventGroupItem_; 644 645 std::map<int, MmapFd> cpuMmap_; 646 std::vector<MmapFd *> MmapRecordHeap_; 647 648 #if !is_mingw 649 std::vector<struct pollfd> pollFds_; 650 #endif 651 const int pollTimeOut_ = 500; // ms 652 size_t pageSize_ = 4096; 653 size_t auxMmapPages_ = 128; 654 bool systemTarget_ = false; 655 bool excludeHiperf_ = false; 656 pid_t selfPid_ = -1; 657 unsigned int mmapPages_ = 0; 658 int clockId_ = -1; 659 uint64_t branchSampleType_ = 0; 660 FILE* reportPtr_ = nullptr; 661 662 SampleStackType sampleStackType_ = SampleStackType::NONE; 663 uint32_t dwarfSampleStackSize_ = MAX_SAMPLE_STACK_SIZE; 664 665 // read records from the ring buffer singleton 666 void ReadRecordFromBuffer(); 667 void ReadRecordFromBufferThread(); 668 669 std::unique_ptr<TrackedCommand> trackedCommand_ = {}; 670 671 StatCallBack reportCallBack_; 672 RecordCallBack recordCallBack_; 673 674 void LoadTracepointEventTypesFromSystem(); 675 bool PerfEventsEnable(const bool); 676 bool AddEvent(const perf_type_id type, const __u64 config, const bool excludeUser = false, 677 const bool excludeKernel = false, const bool followGroup = false); 678 bool AddEvent(const std::string &eventString, const bool followGroup = false); 679 bool AddSpeEvent(const u32 type, const bool followGroup = false); 680 bool IsEventSupport(const perf_type_id type, const __u64 config); 681 bool IsEventAttrSupport(perf_event_attr &attr); 682 683 std::chrono::time_point<std::chrono::steady_clock> trackingStartTime_; 684 std::chrono::time_point<std::chrono::steady_clock> trackingEndTime_; 685 std::chrono::time_point<std::chrono::steady_clock> readingStartTime_; 686 687 std::map<std::string, std::unique_ptr<CountEvent>> countEvents_; 688 689 void PutAllCpus(); 690 bool PrepareFdEvents(); 691 bool CreateFdEvents(); 692 bool StatReport(const __u64 &durationInSec); 693 bool CreateMmap(const FdItem &item, const perf_event_attr &attr); 694 bool CreateSpeMmap(const FdItem &item, const perf_event_attr &attr); 695 GetDefaultAttr()696 const perf_event_attr *GetDefaultAttr() 697 { 698 HLOG_ASSERT(eventGroupItem_.size() > 0); 699 HLOG_ASSERT(eventGroupItem_[0].eventItems.size() > 0); 700 return &(eventGroupItem_.at(0).eventItems.at(0).attr); 701 }; 702 703 OHOS::UniqueFd Open(perf_event_attr &attr, const pid_t pid = 0, const int cpu = -1, const int groupFd = -1, 704 const unsigned long flags = 0); 705 std::unique_ptr<perf_event_attr> CreateDefaultAttr(const perf_type_id type, const __u64 config); 706 707 // for update time thread 708 static bool updateTimeThreadRunning_; 709 static std::atomic<uint64_t> currentTimeSecond_; 710 static void UpdateCurrentTime(); 711 712 // for background track 713 bool backtrack_ = false; 714 bool outputTracking_ = false; 715 uint64_t backtrackTime_ = 0; 716 uint64_t outputEndTime_ = 0; 717 bool IsSkipRecordForBacktrack(const PerfRecordSample& sample); 718 }; 719 } // namespace HiPerf 720 } // namespace Developtools 721 } // namespace OHOS 722 #endif // HIPERF_PERF_EVENTS_H 723