1484543d1Sopenharmony_ci/* 2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License. 5484543d1Sopenharmony_ci * You may obtain a copy of the License at 6484543d1Sopenharmony_ci * 7484543d1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8484543d1Sopenharmony_ci * 9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and 13484543d1Sopenharmony_ci * limitations under the License. 14484543d1Sopenharmony_ci */ 15484543d1Sopenharmony_ci 16484543d1Sopenharmony_ci#include "util.h" 17484543d1Sopenharmony_ci#include <unistd.h> 18484543d1Sopenharmony_ci#include <cstring> 19484543d1Sopenharmony_ci#include <iostream> 20484543d1Sopenharmony_ci#include <functional> 21484543d1Sopenharmony_ci#include <sys/syscall.h> 22484543d1Sopenharmony_ci#include <sys/ioctl.h> 23484543d1Sopenharmony_ci#include <sched.h> 24484543d1Sopenharmony_ci#include <pthread.h> 25484543d1Sopenharmony_ci#include <linux/perf_event.h> 26484543d1Sopenharmony_ci#include "internal_inc/osal.h" 27484543d1Sopenharmony_ci 28484543d1Sopenharmony_ciusing namespace std; 29484543d1Sopenharmony_ci 30484543d1Sopenharmony_ciconstexpr uint32_t PROC_STATUS_LINE_NUM_MAX = 50; 31484543d1Sopenharmony_ci 32484543d1Sopenharmony_ciuint32_t get_proc_memory(pid_t pid) 33484543d1Sopenharmony_ci{ 34484543d1Sopenharmony_ci FILE* fd; 35484543d1Sopenharmony_ci char line[1024] = {0}; 36484543d1Sopenharmony_ci char node_name[64] = {0}; 37484543d1Sopenharmony_ci char vmrss_name[32] = {0}; 38484543d1Sopenharmony_ci uint32_t vmrss_num = 0; 39484543d1Sopenharmony_ci sprintf(node_name, "/proc/%d/status", pid); 40484543d1Sopenharmony_ci fd = fopen(node_name, "r"); 41484543d1Sopenharmony_ci if (fd == nullptr) { 42484543d1Sopenharmony_ci cout << "open " << node_name << " failed" << endl; 43484543d1Sopenharmony_ci return 0; 44484543d1Sopenharmony_ci } 45484543d1Sopenharmony_ci 46484543d1Sopenharmony_ci // VmRSS line is uncertain 47484543d1Sopenharmony_ci for (int i = 0; i < PROC_STATUS_LINE_NUM_MAX; i++) { 48484543d1Sopenharmony_ci if (fgets(line, sizeof(line), fd) == nullptr) { 49484543d1Sopenharmony_ci break; 50484543d1Sopenharmony_ci } 51484543d1Sopenharmony_ci if (strstr(line, "VmRSS:") != nullptr) { 52484543d1Sopenharmony_ci sscanf(line, "%s %d", vmrss_name, &vmrss_num); 53484543d1Sopenharmony_ci break; 54484543d1Sopenharmony_ci } 55484543d1Sopenharmony_ci } 56484543d1Sopenharmony_ci fclose(fd); 57484543d1Sopenharmony_ci return vmrss_num; 58484543d1Sopenharmony_ci} 59484543d1Sopenharmony_civoid set_cur_process_cpu_affinity(int cpuid) 60484543d1Sopenharmony_ci{ 61484543d1Sopenharmony_ci cpu_set_t mask; 62484543d1Sopenharmony_ci CPU_ZERO(&mask); 63484543d1Sopenharmony_ci CPU_SET(cpuid, &mask); 64484543d1Sopenharmony_ci if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { 65484543d1Sopenharmony_ci printf("warning:could not set cpu affinity\n"); 66484543d1Sopenharmony_ci } 67484543d1Sopenharmony_ci cpu_set_t affinity; 68484543d1Sopenharmony_ci CPU_ZERO(&affinity); 69484543d1Sopenharmony_ci if (sched_getaffinity(0, sizeof(affinity), &affinity) == -1) { 70484543d1Sopenharmony_ci printf("warning:could not get cpu affinity\n"); 71484543d1Sopenharmony_ci return; 72484543d1Sopenharmony_ci } 73484543d1Sopenharmony_ci int cpu_num = sysconf(_SC_NPROCESSORS_CONF); 74484543d1Sopenharmony_ci printf("cpu_num:%d\n", cpu_num); 75484543d1Sopenharmony_ci for (int i = 0; i < cpu_num; i++) { 76484543d1Sopenharmony_ci if (CPU_ISSET(i, &affinity)) { 77484543d1Sopenharmony_ci printf("this process is running on cpu:%d\n", i); 78484543d1Sopenharmony_ci } 79484543d1Sopenharmony_ci } 80484543d1Sopenharmony_ci} 81484543d1Sopenharmony_ci#if (defined FFRT_SUPPORT_AOS) 82484543d1Sopenharmony_civoid set_cur_thread_cpu_affinity(int cpuid) 83484543d1Sopenharmony_ci{ 84484543d1Sopenharmony_ci cpu_set_t mask; 85484543d1Sopenharmony_ci CPU_ZERO(&mask); 86484543d1Sopenharmony_ci CPU_SET(cpuid, &mask); 87484543d1Sopenharmony_ci int ret = syscall(__NR_sched_setaffinity, gettid(), sizeof(mask), &mask); 88484543d1Sopenharmony_ci if (ret != 0) { 89484543d1Sopenharmony_ci printf("warning:could not set cpu affinity\n"); 90484543d1Sopenharmony_ci return; 91484543d1Sopenharmony_ci } 92484543d1Sopenharmony_ci printf("this thread:%u is running on cpu:%d\n", GetTid(), cpuid); 93484543d1Sopenharmony_ci} 94484543d1Sopenharmony_ci#else 95484543d1Sopenharmony_civoid set_cur_thread_cpu_affinity(int cpuid) 96484543d1Sopenharmony_ci{ 97484543d1Sopenharmony_ci cpu_set_t mask; 98484543d1Sopenharmony_ci CPU_ZERO(&mask); 99484543d1Sopenharmony_ci CPU_SET(cpuid, &mask); 100484543d1Sopenharmony_ci if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == -1) { 101484543d1Sopenharmony_ci printf("warning:could not set cpu affinity\n"); 102484543d1Sopenharmony_ci } 103484543d1Sopenharmony_ci cpu_set_t affinity; 104484543d1Sopenharmony_ci CPU_ZERO(&affinity); 105484543d1Sopenharmony_ci if (pthread_getaffinity_np(pthread_self(), sizeof(affinity), &affinity) == -1) { 106484543d1Sopenharmony_ci printf("warning:could not get cpu affinity\n"); 107484543d1Sopenharmony_ci return; 108484543d1Sopenharmony_ci } 109484543d1Sopenharmony_ci int cpu_num = sysconf(_SC_NPROCESSORS_CONF); 110484543d1Sopenharmony_ci printf("cpu_num:%d\n", cpu_num); 111484543d1Sopenharmony_ci for (int i = 0; i < cpu_num; i++) { 112484543d1Sopenharmony_ci if (CPU_ISSET(i, &affinity)) { 113484543d1Sopenharmony_ci printf("this thread:%d is running on cpu:%d\n", GetTid(), i); 114484543d1Sopenharmony_ci } 115484543d1Sopenharmony_ci } 116484543d1Sopenharmony_ci} 117484543d1Sopenharmony_ci#endif 118484543d1Sopenharmony_ci 119484543d1Sopenharmony_ci#ifdef FFRT_PERF_EVENT_ENABLE 120484543d1Sopenharmony_cistatic int perf_event_open(struct perf_event_attr* attr, pid_t pid, int cpu, int group_fd, unsigned long flags) 121484543d1Sopenharmony_ci{ 122484543d1Sopenharmony_ci return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); 123484543d1Sopenharmony_ci} 124484543d1Sopenharmony_ci 125484543d1Sopenharmony_ci// sudo perf stat -e instructions:u ./test_main 126484543d1Sopenharmony_ciint perf_single_event(std::function<void()> func, size_t& count, uint32_t event) 127484543d1Sopenharmony_ci{ 128484543d1Sopenharmony_ci int fd; 129484543d1Sopenharmony_ci struct perf_event_attr attr = {}; 130484543d1Sopenharmony_ci attr.type = PERF_TYPE_HARDWARE; 131484543d1Sopenharmony_ci attr.size = sizeof(struct perf_event_attr); 132484543d1Sopenharmony_ci attr.config = event; 133484543d1Sopenharmony_ci attr.disabled = 1; 134484543d1Sopenharmony_ci attr.exclude_kernel = 1; // ignore kernel 135484543d1Sopenharmony_ci attr.exclude_hv = 1; // ignore hyper-visior 136484543d1Sopenharmony_ci 137484543d1Sopenharmony_ci // pid=0,cpu=-1 current process, all cpu 138484543d1Sopenharmony_ci fd = perf_event_open(&attr, 0, -1, -1, 0); 139484543d1Sopenharmony_ci if (fd == -1) { 140484543d1Sopenharmony_ci printf("perf_event_open fail! errno:%d %s\n", errno, strerror(errno)); 141484543d1Sopenharmony_ci return -1; 142484543d1Sopenharmony_ci } 143484543d1Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_RESET, 0); // reset counter 144484543d1Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); // start count 145484543d1Sopenharmony_ci func(); 146484543d1Sopenharmony_ci size_t rcount = read(fd, &count, sizeof(count)); 147484543d1Sopenharmony_ci if (rcount < sizeof(count)) { 148484543d1Sopenharmony_ci printf("perf data read fail! errno:%d %s\n", errno, strerror(errno)); 149484543d1Sopenharmony_ci return -1; 150484543d1Sopenharmony_ci } 151484543d1Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); 152484543d1Sopenharmony_ci close(fd); 153484543d1Sopenharmony_ci return 0; 154484543d1Sopenharmony_ci} 155484543d1Sopenharmony_ci 156484543d1Sopenharmony_ciint perf_event2(std::function<void()> func, struct perf_event2_read_format& data, uint32_t event1, uint32_t event2) 157484543d1Sopenharmony_ci{ 158484543d1Sopenharmony_ci int fd; 159484543d1Sopenharmony_ci struct perf_event_attr attr = {}; 160484543d1Sopenharmony_ci attr.type = PERF_TYPE_HARDWARE; 161484543d1Sopenharmony_ci attr.size = sizeof(struct perf_event_attr); 162484543d1Sopenharmony_ci attr.config = event1; 163484543d1Sopenharmony_ci attr.disabled = 1; 164484543d1Sopenharmony_ci attr.exclude_kernel = 1; 165484543d1Sopenharmony_ci attr.exclude_hv = 1; 166484543d1Sopenharmony_ci attr.read_format = PERF_FORMAT_GROUP; 167484543d1Sopenharmony_ci 168484543d1Sopenharmony_ci // pid=0,cpu=-1 current process, all cpu 169484543d1Sopenharmony_ci fd = perf_event_open(&attr, 0, -1, -1, 0); 170484543d1Sopenharmony_ci if (fd == -1) { 171484543d1Sopenharmony_ci printf("perf_event_open fail! errno:%d %s\n", errno, strerror(errno)); 172484543d1Sopenharmony_ci return -1; 173484543d1Sopenharmony_ci } 174484543d1Sopenharmony_ci attr = {0}; 175484543d1Sopenharmony_ci attr.type = PERF_TYPE_HARDWARE; 176484543d1Sopenharmony_ci attr.size = sizeof(struct perf_event_attr); 177484543d1Sopenharmony_ci attr.config = event2; 178484543d1Sopenharmony_ci attr.disabled = 1; 179484543d1Sopenharmony_ci attr.exclude_kernel = 1; 180484543d1Sopenharmony_ci attr.exclude_hv = 1; 181484543d1Sopenharmony_ci attr.read_format = PERF_FORMAT_GROUP; 182484543d1Sopenharmony_ci int fd2 = perf_event_open(&attr, 0, -1, fd, 0); 183484543d1Sopenharmony_ci if (fd2 == -1) { 184484543d1Sopenharmony_ci printf("perf_event_open fail! errno:%d %s\n", errno, strerror(errno)); 185484543d1Sopenharmony_ci return -1; 186484543d1Sopenharmony_ci } 187484543d1Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); 188484543d1Sopenharmony_ci 189484543d1Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); 190484543d1Sopenharmony_ci 191484543d1Sopenharmony_ci func(); 192484543d1Sopenharmony_ci size_t rcount = read(fd, &data, sizeof(struct perf_event2_read_format)); 193484543d1Sopenharmony_ci if (rcount < sizeof(struct perf_event2_read_format)) { 194484543d1Sopenharmony_ci printf("perf data read fail! errno:%d %s\n", errno, strerror(errno)); 195484543d1Sopenharmony_ci return -1; 196484543d1Sopenharmony_ci } 197484543d1Sopenharmony_ci 198484543d1Sopenharmony_ci ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP); 199484543d1Sopenharmony_ci close(fd); 200484543d1Sopenharmony_ci close(fd2); 201484543d1Sopenharmony_ci return 0; 202484543d1Sopenharmony_ci} 203484543d1Sopenharmony_ci 204484543d1Sopenharmony_ciint perf_event_instructions(std::function<void()> func, size_t& count) 205484543d1Sopenharmony_ci{ 206484543d1Sopenharmony_ci return perf_single_event(func, count, PERF_COUNT_HW_INSTRUCTIONS); 207484543d1Sopenharmony_ci} 208484543d1Sopenharmony_ciint perf_event_cycles(std::function<void()> func, size_t& count) 209484543d1Sopenharmony_ci{ 210484543d1Sopenharmony_ci return perf_single_event(func, count, PERF_COUNT_HW_CPU_CYCLES); 211484543d1Sopenharmony_ci} 212484543d1Sopenharmony_ciint perf_event_branch_instructions(std::function<void()> func, size_t& count) 213484543d1Sopenharmony_ci{ 214484543d1Sopenharmony_ci return perf_single_event(func, count, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); 215484543d1Sopenharmony_ci} 216484543d1Sopenharmony_ciint perf_event_branch_misses(std::function<void()> func, size_t& count) 217484543d1Sopenharmony_ci{ 218484543d1Sopenharmony_ci return perf_single_event(func, count, PERF_COUNT_HW_BRANCH_MISSES); 219484543d1Sopenharmony_ci} 220484543d1Sopenharmony_ci 221484543d1Sopenharmony_ci#else 222484543d1Sopenharmony_ciint perf_event_instructions(std::function<void()> func, size_t& count) 223484543d1Sopenharmony_ci{ 224484543d1Sopenharmony_ci func(); 225484543d1Sopenharmony_ci count = 0; 226484543d1Sopenharmony_ci return 0; 227484543d1Sopenharmony_ci} 228484543d1Sopenharmony_ci 229484543d1Sopenharmony_ciint perf_event_cycles(std::function<void()> func, size_t& count) 230484543d1Sopenharmony_ci{ 231484543d1Sopenharmony_ci func(); 232484543d1Sopenharmony_ci count = 0; 233484543d1Sopenharmony_ci return 0; 234484543d1Sopenharmony_ci} 235484543d1Sopenharmony_ci 236484543d1Sopenharmony_ciint perf_event_branch_instructions(std::function<void()> func, size_t& count) 237484543d1Sopenharmony_ci{ 238484543d1Sopenharmony_ci func(); 239484543d1Sopenharmony_ci count = 0; 240484543d1Sopenharmony_ci return 0; 241484543d1Sopenharmony_ci} 242484543d1Sopenharmony_ci 243484543d1Sopenharmony_ciint perf_event_branch_misses(std::function<void()> func, size_t& count) 244484543d1Sopenharmony_ci{ 245484543d1Sopenharmony_ci func(); 246484543d1Sopenharmony_ci count = 0; 247484543d1Sopenharmony_ci return 0; 248484543d1Sopenharmony_ci} 249484543d1Sopenharmony_ci#endif