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