Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2020 Facebook */
  3#include "bench.h"
  4#include "trigger_bench.skel.h"
  5#include "trace_helpers.h"
  6
  7/* BPF triggering benchmarks */
  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 != 0) {
 17		fprintf(stderr, "benchmark doesn't support 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
106/* make sure call is not inlined and not avoided by compiler, so __weak and
107 * inline asm volatile in the body of the function
108 *
109 * There is a performance difference between uprobing at nop location vs other
110 * instructions. So use two different targets, one of which starts with nop
111 * and another doesn't.
112 *
113 * GCC doesn't generate stack setup preample for these functions due to them
114 * having no input arguments and doing nothing in the body.
115 */
116__weak void uprobe_target_with_nop(void)
117{
118	asm volatile ("nop");
119}
120
121__weak void uprobe_target_without_nop(void)
122{
123	asm volatile ("");
124}
125
126static void *uprobe_base_producer(void *input)
127{
128	while (true) {
129		uprobe_target_with_nop();
130		atomic_inc(&base_hits.value);
131	}
132	return NULL;
133}
134
135static void *uprobe_producer_with_nop(void *input)
136{
137	while (true)
138		uprobe_target_with_nop();
139	return NULL;
140}
141
142static void *uprobe_producer_without_nop(void *input)
143{
144	while (true)
145		uprobe_target_without_nop();
146	return NULL;
147}
148
149static void usetup(bool use_retprobe, bool use_nop)
150{
151	size_t uprobe_offset;
152	struct bpf_link *link;
153
154	setup_libbpf();
155
156	ctx.skel = trigger_bench__open_and_load();
157	if (!ctx.skel) {
158		fprintf(stderr, "failed to open skeleton\n");
159		exit(1);
160	}
161
162	if (use_nop)
163		uprobe_offset = get_uprobe_offset(&uprobe_target_with_nop);
164	else
165		uprobe_offset = get_uprobe_offset(&uprobe_target_without_nop);
166
167	link = bpf_program__attach_uprobe(ctx.skel->progs.bench_trigger_uprobe,
168					  use_retprobe,
169					  -1 /* all PIDs */,
170					  "/proc/self/exe",
171					  uprobe_offset);
172	if (!link) {
173		fprintf(stderr, "failed to attach uprobe!\n");
174		exit(1);
175	}
176	ctx.skel->links.bench_trigger_uprobe = link;
177}
178
179static void uprobe_setup_with_nop(void)
180{
181	usetup(false, true);
182}
183
184static void uretprobe_setup_with_nop(void)
185{
186	usetup(true, true);
187}
188
189static void uprobe_setup_without_nop(void)
190{
191	usetup(false, false);
192}
193
194static void uretprobe_setup_without_nop(void)
195{
196	usetup(true, false);
197}
198
199const struct bench bench_trig_base = {
200	.name = "trig-base",
201	.validate = trigger_validate,
202	.producer_thread = trigger_base_producer,
203	.measure = trigger_base_measure,
204	.report_progress = hits_drops_report_progress,
205	.report_final = hits_drops_report_final,
206};
207
208const struct bench bench_trig_tp = {
209	.name = "trig-tp",
210	.validate = trigger_validate,
211	.setup = trigger_tp_setup,
212	.producer_thread = trigger_producer,
213	.measure = trigger_measure,
214	.report_progress = hits_drops_report_progress,
215	.report_final = hits_drops_report_final,
216};
217
218const struct bench bench_trig_rawtp = {
219	.name = "trig-rawtp",
220	.validate = trigger_validate,
221	.setup = trigger_rawtp_setup,
222	.producer_thread = trigger_producer,
223	.measure = trigger_measure,
224	.report_progress = hits_drops_report_progress,
225	.report_final = hits_drops_report_final,
226};
227
228const struct bench bench_trig_kprobe = {
229	.name = "trig-kprobe",
230	.validate = trigger_validate,
231	.setup = trigger_kprobe_setup,
232	.producer_thread = trigger_producer,
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_fentry = {
239	.name = "trig-fentry",
240	.validate = trigger_validate,
241	.setup = trigger_fentry_setup,
242	.producer_thread = trigger_producer,
243	.measure = trigger_measure,
244	.report_progress = hits_drops_report_progress,
245	.report_final = hits_drops_report_final,
246};
247
248const struct bench bench_trig_fentry_sleep = {
249	.name = "trig-fentry-sleep",
250	.validate = trigger_validate,
251	.setup = trigger_fentry_sleep_setup,
252	.producer_thread = trigger_producer,
253	.measure = trigger_measure,
254	.report_progress = hits_drops_report_progress,
255	.report_final = hits_drops_report_final,
256};
257
258const struct bench bench_trig_fmodret = {
259	.name = "trig-fmodret",
260	.validate = trigger_validate,
261	.setup = trigger_fmodret_setup,
262	.producer_thread = trigger_producer,
263	.measure = trigger_measure,
264	.report_progress = hits_drops_report_progress,
265	.report_final = hits_drops_report_final,
266};
267
268const struct bench bench_trig_uprobe_base = {
269	.name = "trig-uprobe-base",
270	.setup = NULL, /* no uprobe/uretprobe is attached */
271	.producer_thread = uprobe_base_producer,
272	.measure = trigger_base_measure,
273	.report_progress = hits_drops_report_progress,
274	.report_final = hits_drops_report_final,
275};
276
277const struct bench bench_trig_uprobe_with_nop = {
278	.name = "trig-uprobe-with-nop",
279	.setup = uprobe_setup_with_nop,
280	.producer_thread = uprobe_producer_with_nop,
281	.measure = trigger_measure,
282	.report_progress = hits_drops_report_progress,
283	.report_final = hits_drops_report_final,
284};
285
286const struct bench bench_trig_uretprobe_with_nop = {
287	.name = "trig-uretprobe-with-nop",
288	.setup = uretprobe_setup_with_nop,
289	.producer_thread = uprobe_producer_with_nop,
290	.measure = trigger_measure,
291	.report_progress = hits_drops_report_progress,
292	.report_final = hits_drops_report_final,
293};
294
295const struct bench bench_trig_uprobe_without_nop = {
296	.name = "trig-uprobe-without-nop",
297	.setup = uprobe_setup_without_nop,
298	.producer_thread = uprobe_producer_without_nop,
299	.measure = trigger_measure,
300	.report_progress = hits_drops_report_progress,
301	.report_final = hits_drops_report_final,
302};
303
304const struct bench bench_trig_uretprobe_without_nop = {
305	.name = "trig-uretprobe-without-nop",
306	.setup = uretprobe_setup_without_nop,
307	.producer_thread = uprobe_producer_without_nop,
308	.measure = trigger_measure,
309	.report_progress = hits_drops_report_progress,
310	.report_final = hits_drops_report_final,
311};