Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (c) 2016 Facebook
0003  */
0004 #define _GNU_SOURCE
0005 #include <sched.h>
0006 #include <errno.h>
0007 #include <stdio.h>
0008 #include <sys/types.h>
0009 #include <asm/unistd.h>
0010 #include <fcntl.h>
0011 #include <unistd.h>
0012 #include <assert.h>
0013 #include <sys/wait.h>
0014 #include <stdlib.h>
0015 #include <signal.h>
0016 #include <linux/bpf.h>
0017 #include <string.h>
0018 #include <time.h>
0019 #include <bpf/bpf.h>
0020 #include <bpf/libbpf.h>
0021 
0022 #define MAX_CNT 1000000
0023 
0024 static struct bpf_link *links[2];
0025 static struct bpf_object *obj;
0026 static int cnt;
0027 
0028 static __u64 time_get_ns(void)
0029 {
0030     struct timespec ts;
0031 
0032     clock_gettime(CLOCK_MONOTONIC, &ts);
0033     return ts.tv_sec * 1000000000ull + ts.tv_nsec;
0034 }
0035 
0036 static void test_task_rename(int cpu)
0037 {
0038     __u64 start_time;
0039     char buf[] = "test\n";
0040     int i, fd;
0041 
0042     fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
0043     if (fd < 0) {
0044         printf("couldn't open /proc\n");
0045         exit(1);
0046     }
0047     start_time = time_get_ns();
0048     for (i = 0; i < MAX_CNT; i++) {
0049         if (write(fd, buf, sizeof(buf)) < 0) {
0050             printf("task rename failed: %s\n", strerror(errno));
0051             close(fd);
0052             return;
0053         }
0054     }
0055     printf("task_rename:%d: %lld events per sec\n",
0056            cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
0057     close(fd);
0058 }
0059 
0060 static void test_urandom_read(int cpu)
0061 {
0062     __u64 start_time;
0063     char buf[4];
0064     int i, fd;
0065 
0066     fd = open("/dev/urandom", O_RDONLY);
0067     if (fd < 0) {
0068         printf("couldn't open /dev/urandom\n");
0069         exit(1);
0070     }
0071     start_time = time_get_ns();
0072     for (i = 0; i < MAX_CNT; i++) {
0073         if (read(fd, buf, sizeof(buf)) < 0) {
0074             printf("failed to read from /dev/urandom: %s\n", strerror(errno));
0075             close(fd);
0076             return;
0077         }
0078     }
0079     printf("urandom_read:%d: %lld events per sec\n",
0080            cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
0081     close(fd);
0082 }
0083 
0084 static void loop(int cpu, int flags)
0085 {
0086     cpu_set_t cpuset;
0087 
0088     CPU_ZERO(&cpuset);
0089     CPU_SET(cpu, &cpuset);
0090     sched_setaffinity(0, sizeof(cpuset), &cpuset);
0091 
0092     if (flags & 1)
0093         test_task_rename(cpu);
0094     if (flags & 2)
0095         test_urandom_read(cpu);
0096 }
0097 
0098 static void run_perf_test(int tasks, int flags)
0099 {
0100     pid_t pid[tasks];
0101     int i;
0102 
0103     for (i = 0; i < tasks; i++) {
0104         pid[i] = fork();
0105         if (pid[i] == 0) {
0106             loop(i, flags);
0107             exit(0);
0108         } else if (pid[i] == -1) {
0109             printf("couldn't spawn #%d process\n", i);
0110             exit(1);
0111         }
0112     }
0113     for (i = 0; i < tasks; i++) {
0114         int status;
0115 
0116         assert(waitpid(pid[i], &status, 0) == pid[i]);
0117         assert(status == 0);
0118     }
0119 }
0120 
0121 static int load_progs(char *filename)
0122 {
0123     struct bpf_program *prog;
0124     int err = 0;
0125 
0126     obj = bpf_object__open_file(filename, NULL);
0127     err = libbpf_get_error(obj);
0128     if (err < 0) {
0129         fprintf(stderr, "ERROR: opening BPF object file failed\n");
0130         return err;
0131     }
0132 
0133     /* load BPF program */
0134     err = bpf_object__load(obj);
0135     if (err < 0) {
0136         fprintf(stderr, "ERROR: loading BPF object file failed\n");
0137         return err;
0138     }
0139 
0140     bpf_object__for_each_program(prog, obj) {
0141         links[cnt] = bpf_program__attach(prog);
0142         err = libbpf_get_error(links[cnt]);
0143         if (err < 0) {
0144             fprintf(stderr, "ERROR: bpf_program__attach failed\n");
0145             links[cnt] = NULL;
0146             return err;
0147         }
0148         cnt++;
0149     }
0150 
0151     return err;
0152 }
0153 
0154 static void unload_progs(void)
0155 {
0156     while (cnt)
0157         bpf_link__destroy(links[--cnt]);
0158 
0159     bpf_object__close(obj);
0160 }
0161 
0162 int main(int argc, char **argv)
0163 {
0164     int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
0165     int test_flags = ~0;
0166     char filename[256];
0167     int err = 0;
0168 
0169 
0170     if (argc > 1)
0171         test_flags = atoi(argv[1]) ? : test_flags;
0172     if (argc > 2)
0173         num_cpu = atoi(argv[2]) ? : num_cpu;
0174 
0175     if (test_flags & 0x3) {
0176         printf("BASE\n");
0177         run_perf_test(num_cpu, test_flags);
0178     }
0179 
0180     if (test_flags & 0xC) {
0181         snprintf(filename, sizeof(filename),
0182              "%s_kprobe_kern.o", argv[0]);
0183 
0184         printf("w/KPROBE\n");
0185         err = load_progs(filename);
0186         if (!err)
0187             run_perf_test(num_cpu, test_flags >> 2);
0188 
0189         unload_progs();
0190     }
0191 
0192     if (test_flags & 0x30) {
0193         snprintf(filename, sizeof(filename),
0194              "%s_tp_kern.o", argv[0]);
0195         printf("w/TRACEPOINT\n");
0196         err = load_progs(filename);
0197         if (!err)
0198             run_perf_test(num_cpu, test_flags >> 4);
0199 
0200         unload_progs();
0201     }
0202 
0203     if (test_flags & 0xC0) {
0204         snprintf(filename, sizeof(filename),
0205              "%s_raw_tp_kern.o", argv[0]);
0206         printf("w/RAW_TRACEPOINT\n");
0207         err = load_progs(filename);
0208         if (!err)
0209             run_perf_test(num_cpu, test_flags >> 6);
0210 
0211         unload_progs();
0212     }
0213 
0214     return err;
0215 }