root/tools/lib/bpf/hashmap.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. hash_bits
  2. hashmap__add
  3. hashmap__set
  4. hashmap__update
  5. hashmap__append

   1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
   2 
   3 /*
   4  * Generic non-thread safe hash map implementation.
   5  *
   6  * Copyright (c) 2019 Facebook
   7  */
   8 #ifndef __LIBBPF_HASHMAP_H
   9 #define __LIBBPF_HASHMAP_H
  10 
  11 #include <stdbool.h>
  12 #include <stddef.h>
  13 #ifdef __GLIBC__
  14 #include <bits/wordsize.h>
  15 #else
  16 #include <bits/reg.h>
  17 #endif
  18 #include "libbpf_internal.h"
  19 
  20 static inline size_t hash_bits(size_t h, int bits)
  21 {
  22         /* shuffle bits and return requested number of upper bits */
  23         return (h * 11400714819323198485llu) >> (__WORDSIZE - bits);
  24 }
  25 
  26 typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
  27 typedef bool (*hashmap_equal_fn)(const void *key1, const void *key2, void *ctx);
  28 
  29 struct hashmap_entry {
  30         const void *key;
  31         void *value;
  32         struct hashmap_entry *next;
  33 };
  34 
  35 struct hashmap {
  36         hashmap_hash_fn hash_fn;
  37         hashmap_equal_fn equal_fn;
  38         void *ctx;
  39 
  40         struct hashmap_entry **buckets;
  41         size_t cap;
  42         size_t cap_bits;
  43         size_t sz;
  44 };
  45 
  46 #define HASHMAP_INIT(hash_fn, equal_fn, ctx) {  \
  47         .hash_fn = (hash_fn),                   \
  48         .equal_fn = (equal_fn),                 \
  49         .ctx = (ctx),                           \
  50         .buckets = NULL,                        \
  51         .cap = 0,                               \
  52         .cap_bits = 0,                          \
  53         .sz = 0,                                \
  54 }
  55 
  56 void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn,
  57                    hashmap_equal_fn equal_fn, void *ctx);
  58 struct hashmap *hashmap__new(hashmap_hash_fn hash_fn,
  59                              hashmap_equal_fn equal_fn,
  60                              void *ctx);
  61 void hashmap__clear(struct hashmap *map);
  62 void hashmap__free(struct hashmap *map);
  63 
  64 size_t hashmap__size(const struct hashmap *map);
  65 size_t hashmap__capacity(const struct hashmap *map);
  66 
  67 /*
  68  * Hashmap insertion strategy:
  69  * - HASHMAP_ADD - only add key/value if key doesn't exist yet;
  70  * - HASHMAP_SET - add key/value pair if key doesn't exist yet; otherwise,
  71  *   update value;
  72  * - HASHMAP_UPDATE - update value, if key already exists; otherwise, do
  73  *   nothing and return -ENOENT;
  74  * - HASHMAP_APPEND - always add key/value pair, even if key already exists.
  75  *   This turns hashmap into a multimap by allowing multiple values to be
  76  *   associated with the same key. Most useful read API for such hashmap is
  77  *   hashmap__for_each_key_entry() iteration. If hashmap__find() is still
  78  *   used, it will return last inserted key/value entry (first in a bucket
  79  *   chain).
  80  */
  81 enum hashmap_insert_strategy {
  82         HASHMAP_ADD,
  83         HASHMAP_SET,
  84         HASHMAP_UPDATE,
  85         HASHMAP_APPEND,
  86 };
  87 
  88 /*
  89  * hashmap__insert() adds key/value entry w/ various semantics, depending on
  90  * provided strategy value. If a given key/value pair replaced already
  91  * existing key/value pair, both old key and old value will be returned
  92  * through old_key and old_value to allow calling code do proper memory
  93  * management.
  94  */
  95 int hashmap__insert(struct hashmap *map, const void *key, void *value,
  96                     enum hashmap_insert_strategy strategy,
  97                     const void **old_key, void **old_value);
  98 
  99 static inline int hashmap__add(struct hashmap *map,
 100                                const void *key, void *value)
 101 {
 102         return hashmap__insert(map, key, value, HASHMAP_ADD, NULL, NULL);
 103 }
 104 
 105 static inline int hashmap__set(struct hashmap *map,
 106                                const void *key, void *value,
 107                                const void **old_key, void **old_value)
 108 {
 109         return hashmap__insert(map, key, value, HASHMAP_SET,
 110                                old_key, old_value);
 111 }
 112 
 113 static inline int hashmap__update(struct hashmap *map,
 114                                   const void *key, void *value,
 115                                   const void **old_key, void **old_value)
 116 {
 117         return hashmap__insert(map, key, value, HASHMAP_UPDATE,
 118                                old_key, old_value);
 119 }
 120 
 121 static inline int hashmap__append(struct hashmap *map,
 122                                   const void *key, void *value)
 123 {
 124         return hashmap__insert(map, key, value, HASHMAP_APPEND, NULL, NULL);
 125 }
 126 
 127 bool hashmap__delete(struct hashmap *map, const void *key,
 128                      const void **old_key, void **old_value);
 129 
 130 bool hashmap__find(const struct hashmap *map, const void *key, void **value);
 131 
 132 /*
 133  * hashmap__for_each_entry - iterate over all entries in hashmap
 134  * @map: hashmap to iterate
 135  * @cur: struct hashmap_entry * used as a loop cursor
 136  * @bkt: integer used as a bucket loop cursor
 137  */
 138 #define hashmap__for_each_entry(map, cur, bkt)                              \
 139         for (bkt = 0; bkt < map->cap; bkt++)                                \
 140                 for (cur = map->buckets[bkt]; cur; cur = cur->next)
 141 
 142 /*
 143  * hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe
 144  * against removals
 145  * @map: hashmap to iterate
 146  * @cur: struct hashmap_entry * used as a loop cursor
 147  * @tmp: struct hashmap_entry * used as a temporary next cursor storage
 148  * @bkt: integer used as a bucket loop cursor
 149  */
 150 #define hashmap__for_each_entry_safe(map, cur, tmp, bkt)                    \
 151         for (bkt = 0; bkt < map->cap; bkt++)                                \
 152                 for (cur = map->buckets[bkt];                               \
 153                      cur && ({tmp = cur->next; true; });                    \
 154                      cur = tmp)
 155 
 156 /*
 157  * hashmap__for_each_key_entry - iterate over entries associated with given key
 158  * @map: hashmap to iterate
 159  * @cur: struct hashmap_entry * used as a loop cursor
 160  * @key: key to iterate entries for
 161  */
 162 #define hashmap__for_each_key_entry(map, cur, _key)                         \
 163         for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
 164                                              map->cap_bits);                \
 165                      map->buckets ? map->buckets[bkt] : NULL; });           \
 166              cur;                                                           \
 167              cur = cur->next)                                               \
 168                 if (map->equal_fn(cur->key, (_key), map->ctx))
 169 
 170 #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key)               \
 171         for (cur = ({ size_t bkt = hash_bits(map->hash_fn((_key), map->ctx),\
 172                                              map->cap_bits);                \
 173                      cur = map->buckets ? map->buckets[bkt] : NULL; });     \
 174              cur && ({ tmp = cur->next; true; });                           \
 175              cur = tmp)                                                     \
 176                 if (map->equal_fn(cur->key, (_key), map->ctx))
 177 
 178 #endif /* __LIBBPF_HASHMAP_H */

/* [<][>][^][v][top][bottom][index][help] */