1
2
3#include <argp.h>
4#include "bench.h"
5#include "strncmp_bench.skel.h"
6
7static struct strncmp_ctx {
8 struct strncmp_bench *skel;
9} ctx;
10
11static struct strncmp_args {
12 u32 cmp_str_len;
13} args = {
14 .cmp_str_len = 32,
15};
16
17enum {
18 ARG_CMP_STR_LEN = 5000,
19};
20
21static 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
27static 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
46const struct argp bench_strncmp_argp = {
47 .options = opts,
48 .parser = strncmp_parse_arg,
49};
50
51static 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
59static 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
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
101static 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
112static void strncmp_no_helper_setup(void)
113{
114 strncmp_setup();
115 strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper);
116}
117
118static void strncmp_helper_setup(void)
119{
120 strncmp_setup();
121 strncmp_attach_prog(ctx.skel->progs.strncmp_helper);
122}
123
124static void *strncmp_producer(void *ctx)
125{
126 while (true)
127 (void)syscall(__NR_getpgid);
128 return NULL;
129}
130
131static void *strncmp_consumer(void *ctx)
132{
133 return NULL;
134}
135
136static void strncmp_measure(struct bench_res *res)
137{
138 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
139}
140
141const 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
152const 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