linux/tools/testing/selftests/bpf/progs/test_spin_lock.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2019 Facebook
   3#include <linux/bpf.h>
   4#include <linux/version.h>
   5#include <bpf/bpf_helpers.h>
   6
   7struct hmap_elem {
   8        volatile int cnt;
   9        struct bpf_spin_lock lock;
  10        int test_padding;
  11};
  12
  13struct {
  14        __uint(type, BPF_MAP_TYPE_HASH);
  15        __uint(max_entries, 1);
  16        __type(key, int);
  17        __type(value, struct hmap_elem);
  18} hmap SEC(".maps");
  19
  20struct cls_elem {
  21        struct bpf_spin_lock lock;
  22        volatile int cnt;
  23};
  24
  25struct {
  26        __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
  27        __type(key, struct bpf_cgroup_storage_key);
  28        __type(value, struct cls_elem);
  29} cls_map SEC(".maps");
  30
  31struct bpf_vqueue {
  32        struct bpf_spin_lock lock;
  33        /* 4 byte hole */
  34        unsigned long long lasttime;
  35        int credit;
  36        unsigned int rate;
  37};
  38
  39struct {
  40        __uint(type, BPF_MAP_TYPE_ARRAY);
  41        __uint(max_entries, 1);
  42        __type(key, int);
  43        __type(value, struct bpf_vqueue);
  44} vqueue SEC(".maps");
  45
  46#define CREDIT_PER_NS(delta, rate) (((delta) * rate) >> 20)
  47
  48SEC("spin_lock_demo")
  49int bpf_sping_lock_test(struct __sk_buff *skb)
  50{
  51        volatile int credit = 0, max_credit = 100, pkt_len = 64;
  52        struct hmap_elem zero = {}, *val;
  53        unsigned long long curtime;
  54        struct bpf_vqueue *q;
  55        struct cls_elem *cls;
  56        int key = 0;
  57        int err = 0;
  58
  59        val = bpf_map_lookup_elem(&hmap, &key);
  60        if (!val) {
  61                bpf_map_update_elem(&hmap, &key, &zero, 0);
  62                val = bpf_map_lookup_elem(&hmap, &key);
  63                if (!val) {
  64                        err = 1;
  65                        goto err;
  66                }
  67        }
  68        /* spin_lock in hash map run time test */
  69        bpf_spin_lock(&val->lock);
  70        if (val->cnt)
  71                val->cnt--;
  72        else
  73                val->cnt++;
  74        if (val->cnt != 0 && val->cnt != 1)
  75                err = 1;
  76        bpf_spin_unlock(&val->lock);
  77
  78        /* spin_lock in array. virtual queue demo */
  79        q = bpf_map_lookup_elem(&vqueue, &key);
  80        if (!q)
  81                goto err;
  82        curtime = bpf_ktime_get_ns();
  83        bpf_spin_lock(&q->lock);
  84        q->credit += CREDIT_PER_NS(curtime - q->lasttime, q->rate);
  85        q->lasttime = curtime;
  86        if (q->credit > max_credit)
  87                q->credit = max_credit;
  88        q->credit -= pkt_len;
  89        credit = q->credit;
  90        bpf_spin_unlock(&q->lock);
  91
  92        /* spin_lock in cgroup local storage */
  93        cls = bpf_get_local_storage(&cls_map, 0);
  94        bpf_spin_lock(&cls->lock);
  95        cls->cnt++;
  96        bpf_spin_unlock(&cls->lock);
  97
  98err:
  99        return err;
 100}
 101char _license[] SEC("license") = "GPL";
 102