tools/testing/selftests/bpf/progs/res_spin_lock.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/progs/res_spin_lock.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/progs/res_spin_lock.c
Extension
.c
Size
3148 bytes
Lines
148
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 arr_elem {
	struct bpf_res_spin_lock lock;
};

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__uint(max_entries, 64);
	__type(key, int);
	__type(value, struct arr_elem);
} arrmap SEC(".maps");

struct bpf_res_spin_lock lockA __hidden SEC(".data.A");
struct bpf_res_spin_lock lockB __hidden SEC(".data.B");

SEC("tc")
int res_spin_lock_test(struct __sk_buff *ctx)
{
	struct arr_elem *elem1, *elem2;
	int r;

	elem1 = bpf_map_lookup_elem(&arrmap, &(int){0});
	if (!elem1)
		return -1;
	elem2 = bpf_map_lookup_elem(&arrmap, &(int){0});
	if (!elem2)
		return -1;

	r = bpf_res_spin_lock(&elem1->lock);
	if (r)
		return r;
	r = bpf_res_spin_lock(&elem2->lock);
	if (!r) {
		bpf_res_spin_unlock(&elem2->lock);
		bpf_res_spin_unlock(&elem1->lock);
		return -1;
	}
	bpf_res_spin_unlock(&elem1->lock);
	return r != -EDEADLK;
}

SEC("tc")
int res_spin_lock_test_AB(struct __sk_buff *ctx)
{
	int r;

	r = bpf_res_spin_lock(&lockA);
	if (r)
		return !r;
	/* Only unlock if we took the lock. */
	if (!bpf_res_spin_lock(&lockB))
		bpf_res_spin_unlock(&lockB);
	bpf_res_spin_unlock(&lockA);
	return 0;
}

int err;

SEC("tc")
int res_spin_lock_test_BA(struct __sk_buff *ctx)
{
	int r;

	r = bpf_res_spin_lock(&lockB);
	if (r)
		return !r;
	if (!bpf_res_spin_lock(&lockA))
		bpf_res_spin_unlock(&lockA);
	else
		err = -EDEADLK;
	bpf_res_spin_unlock(&lockB);
	return err ?: 0;
}

SEC("tc")
int res_spin_lock_test_held_lock_max(struct __sk_buff *ctx)
{
	struct bpf_res_spin_lock *locks[48] = {};
	struct arr_elem *e;
	u64 time_beg, time;
	int ret = 0, i;

	_Static_assert(ARRAY_SIZE(((struct rqspinlock_held){}).locks) == 31,
		       "RES_NR_HELD assumed to be 31");

	for (i = 0; i < 34; i++) {
		int key = i;

		/* We cannot pass in i as it will get spilled/filled by the compiler and
		 * loses bounds in verifier state.
		 */

Annotation

Implementation Notes