128 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2022. Huawei Technologies Co., Ltd */3#define _GNU_SOURCE4#include <sched.h>5#include <unistd.h>6#include <stdlib.h>7#include <stdbool.h>8#include <errno.h>9#include <string.h>10#include <pthread.h>11 12#include <bpf/bpf.h>13#include <bpf/libbpf.h>14 15#include "test_maps.h"16#include "task_local_storage_helpers.h"17#include "read_bpf_task_storage_busy.skel.h"18 19struct lookup_ctx {20 bool start;21 bool stop;22 int pid_fd;23 int map_fd;24 int loop;25};26 27static void *lookup_fn(void *arg)28{29 struct lookup_ctx *ctx = arg;30 long value;31 int i = 0;32 33 while (!ctx->start)34 usleep(1);35 36 while (!ctx->stop && i++ < ctx->loop)37 bpf_map_lookup_elem(ctx->map_fd, &ctx->pid_fd, &value);38 return NULL;39}40 41static void abort_lookup(struct lookup_ctx *ctx, pthread_t *tids, unsigned int nr)42{43 unsigned int i;44 45 ctx->stop = true;46 ctx->start = true;47 for (i = 0; i < nr; i++)48 pthread_join(tids[i], NULL);49}50 51void test_task_storage_map_stress_lookup(void)52{53#define MAX_NR_THREAD 409654 unsigned int i, nr = 256, loop = 8192, cpu = 0;55 struct read_bpf_task_storage_busy *skel;56 pthread_t tids[MAX_NR_THREAD];57 struct lookup_ctx ctx;58 cpu_set_t old, new;59 const char *cfg;60 int err;61 62 cfg = getenv("TASK_STORAGE_MAP_NR_THREAD");63 if (cfg) {64 nr = atoi(cfg);65 if (nr > MAX_NR_THREAD)66 nr = MAX_NR_THREAD;67 }68 cfg = getenv("TASK_STORAGE_MAP_NR_LOOP");69 if (cfg)70 loop = atoi(cfg);71 cfg = getenv("TASK_STORAGE_MAP_PIN_CPU");72 if (cfg)73 cpu = atoi(cfg);74 75 skel = read_bpf_task_storage_busy__open_and_load();76 err = libbpf_get_error(skel);77 CHECK(err, "open_and_load", "error %d\n", err);78 79 /* Only for a fully preemptible kernel */80 if (!skel->kconfig->CONFIG_PREEMPT) {81 printf("%s SKIP (no CONFIG_PREEMPT)\n", __func__);82 read_bpf_task_storage_busy__destroy(skel);83 skips++;84 return;85 }86 87 /* Save the old affinity setting */88 sched_getaffinity(getpid(), sizeof(old), &old);89 90 /* Pinned on a specific CPU */91 CPU_ZERO(&new);92 CPU_SET(cpu, &new);93 sched_setaffinity(getpid(), sizeof(new), &new);94 95 ctx.start = false;96 ctx.stop = false;97 ctx.pid_fd = sys_pidfd_open(getpid(), 0);98 ctx.map_fd = bpf_map__fd(skel->maps.task);99 ctx.loop = loop;100 for (i = 0; i < nr; i++) {101 err = pthread_create(&tids[i], NULL, lookup_fn, &ctx);102 if (err) {103 abort_lookup(&ctx, tids, i);104 CHECK(err, "pthread_create", "error %d\n", err);105 goto out;106 }107 }108 109 ctx.start = true;110 for (i = 0; i < nr; i++)111 pthread_join(tids[i], NULL);112 113 skel->bss->pid = getpid();114 err = read_bpf_task_storage_busy__attach(skel);115 CHECK(err, "attach", "error %d\n", err);116 117 /* Trigger program */118 syscall(SYS_gettid);119 skel->bss->pid = 0;120 121 CHECK(skel->bss->busy != 0, "bad bpf_task_storage_busy", "got %d\n", skel->bss->busy);122out:123 read_bpf_task_storage_busy__destroy(skel);124 /* Restore affinity setting */125 sched_setaffinity(getpid(), sizeof(old), &old);126 printf("%s:PASS\n", __func__);127}128