]> git.ipfire.org Git - thirdparty/kernel/linux.git/blobdiff - tools/perf/util/env.c
perf bpf: Save bpf_prog_info in a rbtree in perf_env
[thirdparty/kernel/linux.git] / tools / perf / util / env.c
index 4c23779e271a31ce66d0deeb527a658e0ae90ae7..98cd36f0e31795453b628d0f700a919047eae855 100644 (file)
@@ -3,15 +3,97 @@
 #include "env.h"
 #include "sane_ctype.h"
 #include "util.h"
+#include "bpf-event.h"
 #include <errno.h>
 #include <sys/utsname.h>
+#include <bpf/libbpf.h>
 
 struct perf_env perf_env;
 
+void perf_env__insert_bpf_prog_info(struct perf_env *env,
+                                   struct bpf_prog_info_node *info_node)
+{
+       __u32 prog_id = info_node->info_linear->info.id;
+       struct bpf_prog_info_node *node;
+       struct rb_node *parent = NULL;
+       struct rb_node **p;
+
+       down_write(&env->bpf_progs.lock);
+       p = &env->bpf_progs.infos.rb_node;
+
+       while (*p != NULL) {
+               parent = *p;
+               node = rb_entry(parent, struct bpf_prog_info_node, rb_node);
+               if (prog_id < node->info_linear->info.id) {
+                       p = &(*p)->rb_left;
+               } else if (prog_id > node->info_linear->info.id) {
+                       p = &(*p)->rb_right;
+               } else {
+                       pr_debug("duplicated bpf prog info %u\n", prog_id);
+                       goto out;
+               }
+       }
+
+       rb_link_node(&info_node->rb_node, parent, p);
+       rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos);
+       env->bpf_progs.infos_cnt++;
+out:
+       up_write(&env->bpf_progs.lock);
+}
+
+struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
+                                                       __u32 prog_id)
+{
+       struct bpf_prog_info_node *node = NULL;
+       struct rb_node *n;
+
+       down_read(&env->bpf_progs.lock);
+       n = env->bpf_progs.infos.rb_node;
+
+       while (n) {
+               node = rb_entry(n, struct bpf_prog_info_node, rb_node);
+               if (prog_id < node->info_linear->info.id)
+                       n = n->rb_left;
+               else if (prog_id > node->info_linear->info.id)
+                       n = n->rb_right;
+               else
+                       break;
+       }
+
+       up_read(&env->bpf_progs.lock);
+       return node;
+}
+
+/* purge data in bpf_progs.infos tree */
+static void perf_env__purge_bpf(struct perf_env *env)
+{
+       struct rb_root *root;
+       struct rb_node *next;
+
+       down_write(&env->bpf_progs.lock);
+
+       root = &env->bpf_progs.infos;
+       next = rb_first(root);
+
+       while (next) {
+               struct bpf_prog_info_node *node;
+
+               node = rb_entry(next, struct bpf_prog_info_node, rb_node);
+               next = rb_next(&node->rb_node);
+               rb_erase(&node->rb_node, root);
+               free(node);
+       }
+
+       env->bpf_progs.infos_cnt = 0;
+
+       up_write(&env->bpf_progs.lock);
+}
+
 void perf_env__exit(struct perf_env *env)
 {
        int i;
 
+       perf_env__purge_bpf(env);
        zfree(&env->hostname);
        zfree(&env->os_release);
        zfree(&env->version);
@@ -38,6 +120,12 @@ void perf_env__exit(struct perf_env *env)
        zfree(&env->memory_nodes);
 }
 
+void perf_env__init(struct perf_env *env)
+{
+       env->bpf_progs.infos = RB_ROOT;
+       init_rwsem(&env->bpf_progs.lock);
+}
+
 int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
 {
        int i;