18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* Copyright (c) 2016 Facebook 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci#define _GNU_SOURCE 58c2ecf20Sopenharmony_ci#include <sched.h> 68c2ecf20Sopenharmony_ci#include <errno.h> 78c2ecf20Sopenharmony_ci#include <stdio.h> 88c2ecf20Sopenharmony_ci#include <sys/types.h> 98c2ecf20Sopenharmony_ci#include <asm/unistd.h> 108c2ecf20Sopenharmony_ci#include <fcntl.h> 118c2ecf20Sopenharmony_ci#include <unistd.h> 128c2ecf20Sopenharmony_ci#include <assert.h> 138c2ecf20Sopenharmony_ci#include <sys/wait.h> 148c2ecf20Sopenharmony_ci#include <stdlib.h> 158c2ecf20Sopenharmony_ci#include <signal.h> 168c2ecf20Sopenharmony_ci#include <linux/bpf.h> 178c2ecf20Sopenharmony_ci#include <string.h> 188c2ecf20Sopenharmony_ci#include <time.h> 198c2ecf20Sopenharmony_ci#include <sys/resource.h> 208c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 218c2ecf20Sopenharmony_ci#include "bpf_load.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define MAX_CNT 1000000 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic __u64 time_get_ns(void) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct timespec ts; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &ts); 308c2ecf20Sopenharmony_ci return ts.tv_sec * 1000000000ull + ts.tv_nsec; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic void test_task_rename(int cpu) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci __u64 start_time; 368c2ecf20Sopenharmony_ci char buf[] = "test\n"; 378c2ecf20Sopenharmony_ci int i, fd; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci fd = open("/proc/self/comm", O_WRONLY|O_TRUNC); 408c2ecf20Sopenharmony_ci if (fd < 0) { 418c2ecf20Sopenharmony_ci printf("couldn't open /proc\n"); 428c2ecf20Sopenharmony_ci exit(1); 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci start_time = time_get_ns(); 458c2ecf20Sopenharmony_ci for (i = 0; i < MAX_CNT; i++) { 468c2ecf20Sopenharmony_ci if (write(fd, buf, sizeof(buf)) < 0) { 478c2ecf20Sopenharmony_ci printf("task rename failed: %s\n", strerror(errno)); 488c2ecf20Sopenharmony_ci close(fd); 498c2ecf20Sopenharmony_ci return; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci printf("task_rename:%d: %lld events per sec\n", 538c2ecf20Sopenharmony_ci cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 548c2ecf20Sopenharmony_ci close(fd); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void test_urandom_read(int cpu) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci __u64 start_time; 608c2ecf20Sopenharmony_ci char buf[4]; 618c2ecf20Sopenharmony_ci int i, fd; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci fd = open("/dev/urandom", O_RDONLY); 648c2ecf20Sopenharmony_ci if (fd < 0) { 658c2ecf20Sopenharmony_ci printf("couldn't open /dev/urandom\n"); 668c2ecf20Sopenharmony_ci exit(1); 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci start_time = time_get_ns(); 698c2ecf20Sopenharmony_ci for (i = 0; i < MAX_CNT; i++) { 708c2ecf20Sopenharmony_ci if (read(fd, buf, sizeof(buf)) < 0) { 718c2ecf20Sopenharmony_ci printf("failed to read from /dev/urandom: %s\n", strerror(errno)); 728c2ecf20Sopenharmony_ci close(fd); 738c2ecf20Sopenharmony_ci return; 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci printf("urandom_read:%d: %lld events per sec\n", 778c2ecf20Sopenharmony_ci cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 788c2ecf20Sopenharmony_ci close(fd); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic void loop(int cpu, int flags) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci cpu_set_t cpuset; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci CPU_ZERO(&cpuset); 868c2ecf20Sopenharmony_ci CPU_SET(cpu, &cpuset); 878c2ecf20Sopenharmony_ci sched_setaffinity(0, sizeof(cpuset), &cpuset); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (flags & 1) 908c2ecf20Sopenharmony_ci test_task_rename(cpu); 918c2ecf20Sopenharmony_ci if (flags & 2) 928c2ecf20Sopenharmony_ci test_urandom_read(cpu); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic void run_perf_test(int tasks, int flags) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci pid_t pid[tasks]; 988c2ecf20Sopenharmony_ci int i; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 1018c2ecf20Sopenharmony_ci pid[i] = fork(); 1028c2ecf20Sopenharmony_ci if (pid[i] == 0) { 1038c2ecf20Sopenharmony_ci loop(i, flags); 1048c2ecf20Sopenharmony_ci exit(0); 1058c2ecf20Sopenharmony_ci } else if (pid[i] == -1) { 1068c2ecf20Sopenharmony_ci printf("couldn't spawn #%d process\n", i); 1078c2ecf20Sopenharmony_ci exit(1); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 1118c2ecf20Sopenharmony_ci int status; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci assert(waitpid(pid[i], &status, 0) == pid[i]); 1148c2ecf20Sopenharmony_ci assert(status == 0); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic void unload_progs(void) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci close(prog_fd[0]); 1218c2ecf20Sopenharmony_ci close(prog_fd[1]); 1228c2ecf20Sopenharmony_ci close(event_fd[0]); 1238c2ecf20Sopenharmony_ci close(event_fd[1]); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 1298c2ecf20Sopenharmony_ci char filename[256]; 1308c2ecf20Sopenharmony_ci int num_cpu = 8; 1318c2ecf20Sopenharmony_ci int test_flags = ~0; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci setrlimit(RLIMIT_MEMLOCK, &r); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (argc > 1) 1368c2ecf20Sopenharmony_ci test_flags = atoi(argv[1]) ? : test_flags; 1378c2ecf20Sopenharmony_ci if (argc > 2) 1388c2ecf20Sopenharmony_ci num_cpu = atoi(argv[2]) ? : num_cpu; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (test_flags & 0x3) { 1418c2ecf20Sopenharmony_ci printf("BASE\n"); 1428c2ecf20Sopenharmony_ci run_perf_test(num_cpu, test_flags); 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (test_flags & 0xC) { 1468c2ecf20Sopenharmony_ci snprintf(filename, sizeof(filename), 1478c2ecf20Sopenharmony_ci "%s_kprobe_kern.o", argv[0]); 1488c2ecf20Sopenharmony_ci if (load_bpf_file(filename)) { 1498c2ecf20Sopenharmony_ci printf("%s", bpf_log_buf); 1508c2ecf20Sopenharmony_ci return 1; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci printf("w/KPROBE\n"); 1538c2ecf20Sopenharmony_ci run_perf_test(num_cpu, test_flags >> 2); 1548c2ecf20Sopenharmony_ci unload_progs(); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (test_flags & 0x30) { 1588c2ecf20Sopenharmony_ci snprintf(filename, sizeof(filename), 1598c2ecf20Sopenharmony_ci "%s_tp_kern.o", argv[0]); 1608c2ecf20Sopenharmony_ci if (load_bpf_file(filename)) { 1618c2ecf20Sopenharmony_ci printf("%s", bpf_log_buf); 1628c2ecf20Sopenharmony_ci return 1; 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci printf("w/TRACEPOINT\n"); 1658c2ecf20Sopenharmony_ci run_perf_test(num_cpu, test_flags >> 4); 1668c2ecf20Sopenharmony_ci unload_progs(); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (test_flags & 0xC0) { 1708c2ecf20Sopenharmony_ci snprintf(filename, sizeof(filename), 1718c2ecf20Sopenharmony_ci "%s_raw_tp_kern.o", argv[0]); 1728c2ecf20Sopenharmony_ci if (load_bpf_file(filename)) { 1738c2ecf20Sopenharmony_ci printf("%s", bpf_log_buf); 1748c2ecf20Sopenharmony_ci return 1; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci printf("w/RAW_TRACEPOINT\n"); 1778c2ecf20Sopenharmony_ci run_perf_test(num_cpu, test_flags >> 6); 1788c2ecf20Sopenharmony_ci unload_progs(); 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci return 0; 1828c2ecf20Sopenharmony_ci} 183