linux/tools/testing/selftests/bpf/benchs/bench_trigger.c
<<
>>
Prefs
   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 != 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/* make sure call is not inlined and not avoided by compiler, so __weak and
 112 * inline asm volatile in the body of the function
 113 *
 114 * There is a performance difference between uprobing at nop location vs other
 115 * instructions. So use two different targets, one of which starts with nop
 116 * and another doesn't.
 117 *
 118 * GCC doesn't generate stack setup preample for these functions due to them
 119 * having no input arguments and doing nothing in the body.
 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        struct bpf_link *link;
 158
 159        setup_libbpf();
 160
 161        ctx.skel = trigger_bench__open_and_load();
 162        if (!ctx.skel) {
 163                fprintf(stderr, "failed to open skeleton\n");
 164                exit(1);
 165        }
 166
 167        if (use_nop)
 168                uprobe_offset = get_uprobe_offset(&uprobe_target_with_nop);
 169        else
 170                uprobe_offset = get_uprobe_offset(&uprobe_target_without_nop);
 171
 172        link = bpf_program__attach_uprobe(ctx.skel->progs.bench_trigger_uprobe,
 173                                          use_retprobe,
 174                                          -1 /* all PIDs */,
 175                                          "/proc/self/exe",
 176                                          uprobe_offset);
 177        if (!link) {
 178                fprintf(stderr, "failed to attach uprobe!\n");
 179                exit(1);
 180        }
 181        ctx.skel->links.bench_trigger_uprobe = link;
 182}
 183
 184static void uprobe_setup_with_nop(void)
 185{
 186        usetup(false, true);
 187}
 188
 189static void uretprobe_setup_with_nop(void)
 190{
 191        usetup(true, true);
 192}
 193
 194static void uprobe_setup_without_nop(void)
 195{
 196        usetup(false, false);
 197}
 198
 199static void uretprobe_setup_without_nop(void)
 200{
 201        usetup(true, false);
 202}
 203
 204const struct bench bench_trig_base = {
 205        .name = "trig-base",
 206        .validate = trigger_validate,
 207        .producer_thread = trigger_base_producer,
 208        .consumer_thread = trigger_consumer,
 209        .measure = trigger_base_measure,
 210        .report_progress = hits_drops_report_progress,
 211        .report_final = hits_drops_report_final,
 212};
 213
 214const struct bench bench_trig_tp = {
 215        .name = "trig-tp",
 216        .validate = trigger_validate,
 217        .setup = trigger_tp_setup,
 218        .producer_thread = trigger_producer,
 219        .consumer_thread = trigger_consumer,
 220        .measure = trigger_measure,
 221        .report_progress = hits_drops_report_progress,
 222        .report_final = hits_drops_report_final,
 223};
 224
 225const struct bench bench_trig_rawtp = {
 226        .name = "trig-rawtp",
 227        .validate = trigger_validate,
 228        .setup = trigger_rawtp_setup,
 229        .producer_thread = trigger_producer,
 230        .consumer_thread = trigger_consumer,
 231        .measure = trigger_measure,
 232        .report_progress = hits_drops_report_progress,
 233        .report_final = hits_drops_report_final,
 234};
 235
 236const struct bench bench_trig_kprobe = {
 237        .name = "trig-kprobe",
 238        .validate = trigger_validate,
 239        .setup = trigger_kprobe_setup,
 240        .producer_thread = trigger_producer,
 241        .consumer_thread = trigger_consumer,
 242        .measure = trigger_measure,
 243        .report_progress = hits_drops_report_progress,
 244        .report_final = hits_drops_report_final,
 245};
 246
 247const struct bench bench_trig_fentry = {
 248        .name = "trig-fentry",
 249        .validate = trigger_validate,
 250        .setup = trigger_fentry_setup,
 251        .producer_thread = trigger_producer,
 252        .consumer_thread = trigger_consumer,
 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_fentry_sleep = {
 259        .name = "trig-fentry-sleep",
 260        .validate = trigger_validate,
 261        .setup = trigger_fentry_sleep_setup,
 262        .producer_thread = trigger_producer,
 263        .consumer_thread = trigger_consumer,
 264        .measure = trigger_measure,
 265        .report_progress = hits_drops_report_progress,
 266        .report_final = hits_drops_report_final,
 267};
 268
 269const struct bench bench_trig_fmodret = {
 270        .name = "trig-fmodret",
 271        .validate = trigger_validate,
 272        .setup = trigger_fmodret_setup,
 273        .producer_thread = trigger_producer,
 274        .consumer_thread = trigger_consumer,
 275        .measure = trigger_measure,
 276        .report_progress = hits_drops_report_progress,
 277        .report_final = hits_drops_report_final,
 278};
 279
 280const struct bench bench_trig_uprobe_base = {
 281        .name = "trig-uprobe-base",
 282        .setup = NULL, /* no uprobe/uretprobe is attached */
 283        .producer_thread = uprobe_base_producer,
 284        .consumer_thread = trigger_consumer,
 285        .measure = trigger_base_measure,
 286        .report_progress = hits_drops_report_progress,
 287        .report_final = hits_drops_report_final,
 288};
 289
 290const struct bench bench_trig_uprobe_with_nop = {
 291        .name = "trig-uprobe-with-nop",
 292        .setup = uprobe_setup_with_nop,
 293        .producer_thread = uprobe_producer_with_nop,
 294        .consumer_thread = trigger_consumer,
 295        .measure = trigger_measure,
 296        .report_progress = hits_drops_report_progress,
 297        .report_final = hits_drops_report_final,
 298};
 299
 300const struct bench bench_trig_uretprobe_with_nop = {
 301        .name = "trig-uretprobe-with-nop",
 302        .setup = uretprobe_setup_with_nop,
 303        .producer_thread = uprobe_producer_with_nop,
 304        .consumer_thread = trigger_consumer,
 305        .measure = trigger_measure,
 306        .report_progress = hits_drops_report_progress,
 307        .report_final = hits_drops_report_final,
 308};
 309
 310const struct bench bench_trig_uprobe_without_nop = {
 311        .name = "trig-uprobe-without-nop",
 312        .setup = uprobe_setup_without_nop,
 313        .producer_thread = uprobe_producer_without_nop,
 314        .consumer_thread = trigger_consumer,
 315        .measure = trigger_measure,
 316        .report_progress = hits_drops_report_progress,
 317        .report_final = hits_drops_report_final,
 318};
 319
 320const struct bench bench_trig_uretprobe_without_nop = {
 321        .name = "trig-uretprobe-without-nop",
 322        .setup = uretprobe_setup_without_nop,
 323        .producer_thread = uprobe_producer_without_nop,
 324        .consumer_thread = trigger_consumer,
 325        .measure = trigger_measure,
 326        .report_progress = hits_drops_report_progress,
 327        .report_final = hits_drops_report_final,
 328};
 329