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