0001
0002
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
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 }