1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2021. Huawei Technologies Co., Ltd */ 3 #include <argp.h> 4 #include "bench.h" 5 #include "strncmp_bench.skel.h" 6 7 static struct strncmp_ctx { 8 struct strncmp_bench *skel; 9 } ctx; 10 11 static struct strncmp_args { 12 u32 cmp_str_len; 13 } args = { 14 .cmp_str_len = 32, 15 }; 16 17 enum { 18 ARG_CMP_STR_LEN = 5000, 19 }; 20 21 static const struct argp_option opts[] = { 22 { "cmp-str-len", ARG_CMP_STR_LEN, "CMP_STR_LEN", 0, 23 "Set the length of compared string" }, 24 {}, 25 }; 26 27 static error_t strncmp_parse_arg(int key, char *arg, struct argp_state *state) 28 { 29 switch (key) { 30 case ARG_CMP_STR_LEN: 31 args.cmp_str_len = strtoul(arg, NULL, 10); 32 if (!args.cmp_str_len || 33 args.cmp_str_len >= sizeof(ctx.skel->bss->str)) { 34 fprintf(stderr, "Invalid cmp str len (limit %zu)\n", 35 sizeof(ctx.skel->bss->str)); 36 argp_usage(state); 37 } 38 break; 39 default: 40 return ARGP_ERR_UNKNOWN; 41 } 42 43 return 0; 44 } 45 46 const struct argp bench_strncmp_argp = { 47 .options = opts, 48 .parser = strncmp_parse_arg, 49 }; 50 51 static void strncmp_validate(void) 52 { 53 if (env.consumer_cnt != 1) { 54 fprintf(stderr, "strncmp benchmark doesn't support multi-consumer!\n"); 55 exit(1); 56 } 57 } 58 59 static void strncmp_setup(void) 60 { 61 int err; 62 char *target; 63 size_t i, sz; 64 65 sz = sizeof(ctx.skel->rodata->target); 66 if (!sz || sz < sizeof(ctx.skel->bss->str)) { 67 fprintf(stderr, "invalid string size (target %zu, src %zu)\n", 68 sz, sizeof(ctx.skel->bss->str)); 69 exit(1); 70 } 71 72 setup_libbpf(); 73 74 ctx.skel = strncmp_bench__open(); 75 if (!ctx.skel) { 76 fprintf(stderr, "failed to open skeleton\n"); 77 exit(1); 78 } 79 80 srandom(time(NULL)); 81 target = ctx.skel->rodata->target; 82 for (i = 0; i < sz - 1; i++) 83 target[i] = '1' + random() % 9; 84 target[sz - 1] = '\0'; 85 86 ctx.skel->rodata->cmp_str_len = args.cmp_str_len; 87 88 memcpy(ctx.skel->bss->str, target, args.cmp_str_len); 89 ctx.skel->bss->str[args.cmp_str_len] = '\0'; 90 /* Make bss->str < rodata->target */ 91 ctx.skel->bss->str[args.cmp_str_len - 1] -= 1; 92 93 err = strncmp_bench__load(ctx.skel); 94 if (err) { 95 fprintf(stderr, "failed to load skeleton\n"); 96 strncmp_bench__destroy(ctx.skel); 97 exit(1); 98 } 99 } 100 101 static void strncmp_attach_prog(struct bpf_program *prog) 102 { 103 struct bpf_link *link; 104 105 link = bpf_program__attach(prog); 106 if (!link) { 107 fprintf(stderr, "failed to attach program!\n"); 108 exit(1); 109 } 110 } 111 112 static void strncmp_no_helper_setup(void) 113 { 114 strncmp_setup(); 115 strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper); 116 } 117 118 static void strncmp_helper_setup(void) 119 { 120 strncmp_setup(); 121 strncmp_attach_prog(ctx.skel->progs.strncmp_helper); 122 } 123 124 static void *strncmp_producer(void *ctx) 125 { 126 while (true) 127 (void)syscall(__NR_getpgid); 128 return NULL; 129 } 130 131 static void *strncmp_consumer(void *ctx) 132 { 133 return NULL; 134 } 135 136 static void strncmp_measure(struct bench_res *res) 137 { 138 res->hits = atomic_swap(&ctx.skel->bss->hits, 0); 139 } 140 141 const struct bench bench_strncmp_no_helper = { 142 .name = "strncmp-no-helper", 143 .validate = strncmp_validate, 144 .setup = strncmp_no_helper_setup, 145 .producer_thread = strncmp_producer, 146 .consumer_thread = strncmp_consumer, 147 .measure = strncmp_measure, 148 .report_progress = hits_drops_report_progress, 149 .report_final = hits_drops_report_final, 150 }; 151 152 const struct bench bench_strncmp_helper = { 153 .name = "strncmp-helper", 154 .validate = strncmp_validate, 155 .setup = strncmp_helper_setup, 156 .producer_thread = strncmp_producer, 157 .consumer_thread = strncmp_consumer, 158 .measure = strncmp_measure, 159 .report_progress = hits_drops_report_progress, 160 .report_final = hits_drops_report_final, 161 }; 162