1
2
3#include "bench.h"
4#include "trigger_bench.skel.h"
5#include "trace_helpers.h"
6
7
8static struct trigger_ctx {
9 struct trigger_bench *skel;
10} ctx;
11
12static struct counter base_hits;
13
14static void trigger_validate(void)
15{
16 if (env.consumer_cnt != 1) {
17 fprintf(stderr, "benchmark doesn't support multi-consumer!\n");
18 exit(1);
19 }
20}
21
22static void *trigger_base_producer(void *input)
23{
24 while (true) {
25 (void)syscall(__NR_getpgid);
26 atomic_inc(&base_hits.value);
27 }
28 return NULL;
29}
30
31static void trigger_base_measure(struct bench_res *res)
32{
33 res->hits = atomic_swap(&base_hits.value, 0);
34}
35
36static void *trigger_producer(void *input)
37{
38 while (true)
39 (void)syscall(__NR_getpgid);
40 return NULL;
41}
42
43static void trigger_measure(struct bench_res *res)
44{
45 res->hits = atomic_swap(&ctx.skel->bss->hits, 0);
46}
47
48static void setup_ctx(void)
49{
50 setup_libbpf();
51
52 ctx.skel = trigger_bench__open_and_load();
53 if (!ctx.skel) {
54 fprintf(stderr, "failed to open skeleton\n");
55 exit(1);
56 }
57}
58
59static void attach_bpf(struct bpf_program *prog)
60{
61 struct bpf_link *link;
62
63 link = bpf_program__attach(prog);
64 if (!link) {
65 fprintf(stderr, "failed to attach program!\n");
66 exit(1);
67 }
68}
69
70static void trigger_tp_setup(void)
71{
72 setup_ctx();
73 attach_bpf(ctx.skel->progs.bench_trigger_tp);
74}
75
76static void trigger_rawtp_setup(void)
77{
78 setup_ctx();
79 attach_bpf(ctx.skel->progs.bench_trigger_raw_tp);
80}
81
82static void trigger_kprobe_setup(void)
83{
84 setup_ctx();
85 attach_bpf(ctx.skel->progs.bench_trigger_kprobe);
86}
87
88static void trigger_fentry_setup(void)
89{
90 setup_ctx();
91 attach_bpf(ctx.skel->progs.bench_trigger_fentry);
92}
93
94static void trigger_fentry_sleep_setup(void)
95{
96 setup_ctx();
97 attach_bpf(ctx.skel->progs.bench_trigger_fentry_sleep);
98}
99
100static void trigger_fmodret_setup(void)
101{
102 setup_ctx();
103 attach_bpf(ctx.skel->progs.bench_trigger_fmodret);
104}
105
106static void *trigger_consumer(void *input)
107{
108 return NULL;
109}
110
111
112
113
114
115
116
117
118
119
120
121__weak void uprobe_target_with_nop(void)
122{
123 asm volatile ("nop");
124}
125
126__weak void uprobe_target_without_nop(void)
127{
128 asm volatile ("");
129}
130
131static void *uprobe_base_producer(void *input)
132{
133 while (true) {
134 uprobe_target_with_nop();
135 atomic_inc(&base_hits.value);
136 }
137 return NULL;
138}
139
140static void *uprobe_producer_with_nop(void *input)
141{
142 while (true)
143 uprobe_target_with_nop();
144 return NULL;
145}
146
147static void *uprobe_producer_without_nop(void *input)
148{
149 while (true)
150 uprobe_target_without_nop();
151 return NULL;
152}
153
154static void usetup(bool use_retprobe, bool use_nop)
155{
156 size_t uprobe_offset;
157 ssize_t base_addr;
158 struct bpf_link *link;
159
160 setup_libbpf();
161
162 ctx.skel = trigger_bench__open_and_load();
163 if (!ctx.skel) {
164 fprintf(stderr, "failed to open skeleton\n");
165 exit(1);
166 }
167
168 base_addr = get_base_addr();
169 if (use_nop)
170 uprobe_offset = get_uprobe_offset(&uprobe_target_with_nop, base_addr);
171 else
172 uprobe_offset = get_uprobe_offset(&uprobe_target_without_nop, base_addr);
173
174 link = bpf_program__attach_uprobe(ctx.skel->progs.bench_trigger_uprobe,
175 use_retprobe,
176 -1 ,
177 "/proc/self/exe",
178 uprobe_offset);
179 if (!link) {
180 fprintf(stderr, "failed to attach uprobe!\n");
181 exit(1);
182 }
183 ctx.skel->links.bench_trigger_uprobe = link;
184}
185
186static void uprobe_setup_with_nop(void)
187{
188 usetup(false, true);
189}
190
191static void uretprobe_setup_with_nop(void)
192{
193 usetup(true, true);
194}
195
196static void uprobe_setup_without_nop(void)
197{
198 usetup(false, false);
199}
200
201static void uretprobe_setup_without_nop(void)
202{
203 usetup(true, false);
204}
205
206const struct bench bench_trig_base = {
207 .name = "trig-base",
208 .validate = trigger_validate,
209 .producer_thread = trigger_base_producer,
210 .consumer_thread = trigger_consumer,
211 .measure = trigger_base_measure,
212 .report_progress = hits_drops_report_progress,
213 .report_final = hits_drops_report_final,
214};
215
216const struct bench bench_trig_tp = {
217 .name = "trig-tp",
218 .validate = trigger_validate,
219 .setup = trigger_tp_setup,
220 .producer_thread = trigger_producer,
221 .consumer_thread = trigger_consumer,
222 .measure = trigger_measure,
223 .report_progress = hits_drops_report_progress,
224 .report_final = hits_drops_report_final,
225};
226
227const struct bench bench_trig_rawtp = {
228 .name = "trig-rawtp",
229 .validate = trigger_validate,
230 .setup = trigger_rawtp_setup,
231 .producer_thread = trigger_producer,
232 .consumer_thread = trigger_consumer,
233 .measure = trigger_measure,
234 .report_progress = hits_drops_report_progress,
235 .report_final = hits_drops_report_final,
236};
237
238const struct bench bench_trig_kprobe = {
239 .name = "trig-kprobe",
240 .validate = trigger_validate,
241 .setup = trigger_kprobe_setup,
242 .producer_thread = trigger_producer,
243 .consumer_thread = trigger_consumer,
244 .measure = trigger_measure,
245 .report_progress = hits_drops_report_progress,
246 .report_final = hits_drops_report_final,
247};
248
249const struct bench bench_trig_fentry = {
250 .name = "trig-fentry",
251 .validate = trigger_validate,
252 .setup = trigger_fentry_setup,
253 .producer_thread = trigger_producer,
254 .consumer_thread = trigger_consumer,
255 .measure = trigger_measure,
256 .report_progress = hits_drops_report_progress,
257 .report_final = hits_drops_report_final,
258};
259
260const struct bench bench_trig_fentry_sleep = {
261 .name = "trig-fentry-sleep",
262 .validate = trigger_validate,
263 .setup = trigger_fentry_sleep_setup,
264 .producer_thread = trigger_producer,
265 .consumer_thread = trigger_consumer,
266 .measure = trigger_measure,
267 .report_progress = hits_drops_report_progress,
268 .report_final = hits_drops_report_final,
269};
270
271const struct bench bench_trig_fmodret = {
272 .name = "trig-fmodret",
273 .validate = trigger_validate,
274 .setup = trigger_fmodret_setup,
275 .producer_thread = trigger_producer,
276 .consumer_thread = trigger_consumer,
277 .measure = trigger_measure,
278 .report_progress = hits_drops_report_progress,
279 .report_final = hits_drops_report_final,
280};
281
282const struct bench bench_trig_uprobe_base = {
283 .name = "trig-uprobe-base",
284 .setup = NULL,
285 .producer_thread = uprobe_base_producer,
286 .consumer_thread = trigger_consumer,
287 .measure = trigger_base_measure,
288 .report_progress = hits_drops_report_progress,
289 .report_final = hits_drops_report_final,
290};
291
292const struct bench bench_trig_uprobe_with_nop = {
293 .name = "trig-uprobe-with-nop",
294 .setup = uprobe_setup_with_nop,
295 .producer_thread = uprobe_producer_with_nop,
296 .consumer_thread = trigger_consumer,
297 .measure = trigger_measure,
298 .report_progress = hits_drops_report_progress,
299 .report_final = hits_drops_report_final,
300};
301
302const struct bench bench_trig_uretprobe_with_nop = {
303 .name = "trig-uretprobe-with-nop",
304 .setup = uretprobe_setup_with_nop,
305 .producer_thread = uprobe_producer_with_nop,
306 .consumer_thread = trigger_consumer,
307 .measure = trigger_measure,
308 .report_progress = hits_drops_report_progress,
309 .report_final = hits_drops_report_final,
310};
311
312const struct bench bench_trig_uprobe_without_nop = {
313 .name = "trig-uprobe-without-nop",
314 .setup = uprobe_setup_without_nop,
315 .producer_thread = uprobe_producer_without_nop,
316 .consumer_thread = trigger_consumer,
317 .measure = trigger_measure,
318 .report_progress = hits_drops_report_progress,
319 .report_final = hits_drops_report_final,
320};
321
322const struct bench bench_trig_uretprobe_without_nop = {
323 .name = "trig-uretprobe-without-nop",
324 .setup = uretprobe_setup_without_nop,
325 .producer_thread = uprobe_producer_without_nop,
326 .consumer_thread = trigger_consumer,
327 .measure = trigger_measure,
328 .report_progress = hits_drops_report_progress,
329 .report_final = hits_drops_report_final,
330};
331