// SPDX-License-Identifier: GPL-2.0 /* Copyright (C) 2021. Huawei Technologies Co., Ltd */ #include #include "bench.h" #include "strncmp_bench.skel.h" static struct strncmp_ctx { struct strncmp_bench *skel; } ctx; static struct strncmp_args { u32 cmp_str_len; } args = { .cmp_str_len = 32, }; enum { ARG_CMP_STR_LEN = 5000, }; static const struct argp_option opts[] = { { "cmp-str-len", ARG_CMP_STR_LEN, "CMP_STR_LEN", 0, "Set the length of compared string" }, {}, }; static error_t strncmp_parse_arg(int key, char *arg, struct argp_state *state) { switch (key) { case ARG_CMP_STR_LEN: args.cmp_str_len = strtoul(arg, NULL, 10); if (!args.cmp_str_len || args.cmp_str_len >= sizeof(ctx.skel->bss->str)) { fprintf(stderr, "Invalid cmp str len (limit %zu)\n", sizeof(ctx.skel->bss->str)); argp_usage(state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } const struct argp bench_strncmp_argp = { .options = opts, .parser = strncmp_parse_arg, }; static void strncmp_validate(void) { if (env.consumer_cnt != 1) { fprintf(stderr, "strncmp benchmark doesn't support multi-consumer!\n"); exit(1); } } static void strncmp_setup(void) { int err; char *target; size_t i, sz; sz = sizeof(ctx.skel->rodata->target); if (!sz || sz < sizeof(ctx.skel->bss->str)) { fprintf(stderr, "invalid string size (target %zu, src %zu)\n", sz, sizeof(ctx.skel->bss->str)); exit(1); } setup_libbpf(); ctx.skel = strncmp_bench__open(); if (!ctx.skel) { fprintf(stderr, "failed to open skeleton\n"); exit(1); } srandom(time(NULL)); target = ctx.skel->rodata->target; for (i = 0; i < sz - 1; i++) target[i] = '1' + random() % 9; target[sz - 1] = '\0'; ctx.skel->rodata->cmp_str_len = args.cmp_str_len; memcpy(ctx.skel->bss->str, target, args.cmp_str_len); ctx.skel->bss->str[args.cmp_str_len] = '\0'; /* Make bss->str < rodata->target */ ctx.skel->bss->str[args.cmp_str_len - 1] -= 1; err = strncmp_bench__load(ctx.skel); if (err) { fprintf(stderr, "failed to load skeleton\n"); strncmp_bench__destroy(ctx.skel); exit(1); } } static void strncmp_attach_prog(struct bpf_program *prog) { struct bpf_link *link; link = bpf_program__attach(prog); if (!link) { fprintf(stderr, "failed to attach program!\n"); exit(1); } } static void strncmp_no_helper_setup(void) { strncmp_setup(); strncmp_attach_prog(ctx.skel->progs.strncmp_no_helper); } static void strncmp_helper_setup(void) { strncmp_setup(); strncmp_attach_prog(ctx.skel->progs.strncmp_helper); } static void *strncmp_producer(void *ctx) { while (true) (void)syscall(__NR_getpgid); return NULL; } static void *strncmp_consumer(void *ctx) { return NULL; } static void strncmp_measure(struct bench_res *res) { res->hits = atomic_swap(&ctx.skel->bss->hits, 0); } const struct bench bench_strncmp_no_helper = { .name = "strncmp-no-helper", .argp = &bench_strncmp_argp, .validate = strncmp_validate, .setup = strncmp_no_helper_setup, .producer_thread = strncmp_producer, .consumer_thread = strncmp_consumer, .measure = strncmp_measure, .report_progress = hits_drops_report_progress, .report_final = hits_drops_report_final, }; const struct bench bench_strncmp_helper = { .name = "strncmp-helper", .argp = &bench_strncmp_argp, .validate = strncmp_validate, .setup = strncmp_helper_setup, .producer_thread = strncmp_producer, .consumer_thread = strncmp_consumer, .measure = strncmp_measure, .report_progress = hits_drops_report_progress, .report_final = hits_drops_report_final, };