tools/testing/selftests/bpf/map_tests/map_percpu_stats.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/map_tests/map_percpu_stats.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/map_tests/map_percpu_stats.c
Extension
.c
Size
12750 bytes
Lines
489
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct upsert_opts {
	__u32 map_type;
	int map_fd;
	__u32 n;
	bool retry_for_nomem;
};

static int create_small_hash(void)
{
	int map_fd;

	map_fd = bpf_map_create(BPF_MAP_TYPE_HASH, "small", 4, 4, 4, NULL);
	CHECK(map_fd < 0, "bpf_map_create()", "error:%s (name=%s)\n",
			strerror(errno), "small");

	return map_fd;
}

static bool retry_for_nomem_fn(int err)
{
	return err == ENOMEM;
}

static void *patch_map_thread(void *arg)
{
	/* 8KB is enough for 1024 CPUs. And it is shared between N_THREADS. */
	static __u8 blob[8 << 10];
	struct upsert_opts *opts = arg;
	void *val_ptr;
	int val;
	int ret;
	int i;

	for (i = 0; i < opts->n; i++) {
		if (opts->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
			val = create_small_hash();
			val_ptr = &val;
		} else if (is_percpu(opts->map_type)) {
			val_ptr = blob;
		} else {
			val = rand();
			val_ptr = &val;
		}

		/* 2 seconds may be enough ? */
		if (opts->retry_for_nomem)
			ret = map_update_retriable(opts->map_fd, &i, val_ptr, 0,
						   40, retry_for_nomem_fn);
		else
			ret = bpf_map_update_elem(opts->map_fd, &i, val_ptr, 0);
		CHECK(ret < 0, "bpf_map_update_elem", "key=%d error: %s\n", i, strerror(errno));

		if (opts->map_type == BPF_MAP_TYPE_HASH_OF_MAPS)
			close(val);
	}
	return NULL;
}

static void upsert_elements(struct upsert_opts *opts)
{
	pthread_t threads[N_THREADS];
	int ret;
	int i;

	for (i = 0; i < ARRAY_SIZE(threads); i++) {
		ret = pthread_create(&i[threads], NULL, patch_map_thread, opts);
		CHECK(ret != 0, "pthread_create", "error: %s\n", strerror(ret));
	}

	for (i = 0; i < ARRAY_SIZE(threads); i++) {
		ret = pthread_join(i[threads], NULL);
		CHECK(ret != 0, "pthread_join", "error: %s\n", strerror(ret));
	}
}

static __u32 read_cur_elements(int iter_fd)
{
	char buf[64];
	ssize_t n;
	__u32 ret;

	n = read(iter_fd, buf, sizeof(buf)-1);
	CHECK(n <= 0, "read", "error: %s\n", strerror(errno));
	buf[n] = '\0';

	errno = 0;
	ret = (__u32)strtol(buf, NULL, 10);
	CHECK(errno != 0, "strtol", "error: %s\n", strerror(errno));

	return ret;

Annotation

Implementation Notes