xref: /linux/tools/testing/selftests/bpf/progs/bench_bpf_timing.bpf.h (revision b2128290c29902315e632ea59e0504d6bc9e9b42)
1*08158c11SPuranjay Mohan /* SPDX-License-Identifier: GPL-2.0 */
2*08158c11SPuranjay Mohan /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3*08158c11SPuranjay Mohan 
4*08158c11SPuranjay Mohan #ifndef __BENCH_BPF_TIMING_BPF_H__
5*08158c11SPuranjay Mohan #define __BENCH_BPF_TIMING_BPF_H__
6*08158c11SPuranjay Mohan 
7*08158c11SPuranjay Mohan #include <stdbool.h>
8*08158c11SPuranjay Mohan #include <linux/bpf.h>
9*08158c11SPuranjay Mohan #include <bpf/bpf_helpers.h>
10*08158c11SPuranjay Mohan #include <bpf_may_goto.h>
11*08158c11SPuranjay Mohan 
12*08158c11SPuranjay Mohan #ifndef BENCH_NR_SAMPLES
13*08158c11SPuranjay Mohan #define BENCH_NR_SAMPLES	4096
14*08158c11SPuranjay Mohan #endif
15*08158c11SPuranjay Mohan #ifndef BENCH_NR_CPUS
16*08158c11SPuranjay Mohan #define BENCH_NR_CPUS		256
17*08158c11SPuranjay Mohan #endif
18*08158c11SPuranjay Mohan #define BENCH_CPU_MASK		(BENCH_NR_CPUS - 1)
19*08158c11SPuranjay Mohan 
20*08158c11SPuranjay Mohan __u64 timing_samples[BENCH_NR_CPUS][BENCH_NR_SAMPLES];
21*08158c11SPuranjay Mohan __u32 timing_idx[BENCH_NR_CPUS];
22*08158c11SPuranjay Mohan 
23*08158c11SPuranjay Mohan volatile __u32 batch_iters;
24*08158c11SPuranjay Mohan volatile __u32 timing_enabled;
25*08158c11SPuranjay Mohan 
26*08158c11SPuranjay Mohan static __always_inline void bench_record_sample(__u64 elapsed_ns)
27*08158c11SPuranjay Mohan {
28*08158c11SPuranjay Mohan 	__u32 cpu, idx;
29*08158c11SPuranjay Mohan 
30*08158c11SPuranjay Mohan 	if (!timing_enabled)
31*08158c11SPuranjay Mohan 		return;
32*08158c11SPuranjay Mohan 
33*08158c11SPuranjay Mohan 	cpu = bpf_get_smp_processor_id() & BENCH_CPU_MASK;
34*08158c11SPuranjay Mohan 	idx = timing_idx[cpu];
35*08158c11SPuranjay Mohan 
36*08158c11SPuranjay Mohan 	if (idx >= BENCH_NR_SAMPLES)
37*08158c11SPuranjay Mohan 		return;
38*08158c11SPuranjay Mohan 
39*08158c11SPuranjay Mohan 	timing_samples[cpu][idx] = elapsed_ns;
40*08158c11SPuranjay Mohan 	timing_idx[cpu] = idx + 1;
41*08158c11SPuranjay Mohan }
42*08158c11SPuranjay Mohan 
43*08158c11SPuranjay Mohan /*
44*08158c11SPuranjay Mohan  * @body:  expression to time; return value (int) stored in __bench_result.
45*08158c11SPuranjay Mohan  * @reset: undo body's side-effects so each iteration starts identically.
46*08158c11SPuranjay Mohan  *         May reference __bench_result.  Use ({}) for empty reset.
47*08158c11SPuranjay Mohan  *
48*08158c11SPuranjay Mohan  * Runs batch_iters timed iterations, then one untimed iteration whose
49*08158c11SPuranjay Mohan  * return value the macro evaluates to (for validation).
50*08158c11SPuranjay Mohan  */
51*08158c11SPuranjay Mohan #define BENCH_BPF_LOOP(body, reset) ({					\
52*08158c11SPuranjay Mohan 	__u64 __bench_start = bpf_ktime_get_ns();			\
53*08158c11SPuranjay Mohan 	__u32 __bench_i;						\
54*08158c11SPuranjay Mohan 	int __bench_result;						\
55*08158c11SPuranjay Mohan 									\
56*08158c11SPuranjay Mohan 	for (__bench_i = 0;						\
57*08158c11SPuranjay Mohan 	     __bench_i < batch_iters && can_loop;			\
58*08158c11SPuranjay Mohan 	     __bench_i++) {						\
59*08158c11SPuranjay Mohan 		__bench_result = (body);				\
60*08158c11SPuranjay Mohan 		reset;							\
61*08158c11SPuranjay Mohan 	}								\
62*08158c11SPuranjay Mohan 									\
63*08158c11SPuranjay Mohan 	bench_record_sample(bpf_ktime_get_ns() - __bench_start);	\
64*08158c11SPuranjay Mohan 									\
65*08158c11SPuranjay Mohan 	__bench_result = (body);					\
66*08158c11SPuranjay Mohan 	__bench_result;							\
67*08158c11SPuranjay Mohan })
68*08158c11SPuranjay Mohan 
69*08158c11SPuranjay Mohan #endif /* __BENCH_BPF_TIMING_BPF_H__ */
70