23 #ifndef __included_bihash_template_h__ 24 #define __included_bihash_template_h__ 32 #error BIHASH_TYPE not defined 36 #define __bv(a,b) _bv(a,b) 37 #define BV(a) __bv(a,BIHASH_TYPE) 39 #define _bvt(a,b) a##b##_t 40 #define __bvt(a,b) _bvt(a,b) 41 #define BVT(a) __bvt(a,BIHASH_TYPE) 43 typedef struct BV (clib_bihash_value)
47 BVT (clib_bihash_kv) kvp[BIHASH_KVP_PER_PAGE];
48 struct BV (clib_bihash_value) * next_free;
50 }
BVT (clib_bihash_value);
52 #if BIHASH_KVP_CACHE_SIZE > 5 53 #error Requested KVP cache LRU data exceeds 16 bits 69 #if BIHASH_KVP_CACHE_SIZE > 0 73 }
BVT (clib_bihash_bucket);
75 #if BIHASH_KVP_CACHE_SIZE == 0 81 BVT (clib_bihash_value) * values;
82 BVT (clib_bihash_bucket) * buckets;
83 volatile u32 *writer_lock;
85 BVT (clib_bihash_value) ** working_copies;
86 int *working_copy_lengths;
87 BVT (clib_bihash_bucket) saved_bucket;
96 BVT (clib_bihash_value) ** freelists;
103 uword alloc_arena_next;
104 uword alloc_arena_size;
115 BV (clib_bihash_update_lru) (
BVT (clib_bihash_bucket) * b,
u8 slot)
117 #if BIHASH_KVP_CACHE_SIZE > 1 118 u16 value, tmp, mask;
135 value = b->cache_lru;
142 found_lru_pos = ((tmp & (7 << 3)) == 0) ? 1 : 0;
144 found_lru_pos = ((tmp & (7 << 6)) == 0) ? 2 : found_lru_pos;
146 found_lru_pos = ((tmp & (7 << 9)) == 0) ? 3 : found_lru_pos;
148 found_lru_pos = ((tmp & (7 << 12)) == 0) ? 4 : found_lru_pos;
153 mask = 0xFFFF << found_lru_pos;
154 mask <<= found_lru_pos;
155 mask <<= found_lru_pos;
162 save_hi = value & mask;
164 value = save_hi | (tmp << 3) | slot;
166 b->cache_lru = value;
171 BV (clib_bihash_update_lru_not_inline) (
BVT (clib_bihash_bucket) * b,
174 static inline u8 BV (clib_bihash_get_lru) (
BVT (clib_bihash_bucket) * b)
176 #if BIHASH_KVP_CACHE_SIZE > 0 183 static inline void BV (clib_bihash_reset_cache) (
BVT (clib_bihash_bucket) * b)
185 #if BIHASH_KVP_CACHE_SIZE > 0 186 u16 initial_lru_value;
188 memset (b->cache, 0xff, sizeof (b->cache));
195 initial_lru_value = 0;
197 initial_lru_value = (0 << 3) | (1 << 0);
199 initial_lru_value = (0 << 6) | (1 << 3) | (2 << 0);
201 initial_lru_value = (0 << 9) | (1 << 6) | (2 << 3) | (3 << 0);
203 initial_lru_value = (0 << 12) | (1 << 9) | (2 << 6) | (3 << 3) | (4 << 0);
205 b->cache_lru = initial_lru_value;
209 static inline int BV (clib_bihash_lock_bucket) (
BVT (clib_bihash_bucket) * b)
211 #if BIHASH_KVP_CACHE_SIZE > 0 215 cache_lru_bit = 1 << 15;
217 rv = __sync_fetch_and_or (&b->cache_lru, cache_lru_bit);
225 static inline void BV (clib_bihash_unlock_bucket)
226 (
BVT (clib_bihash_bucket) * b)
228 #if BIHASH_KVP_CACHE_SIZE > 0 231 cache_lru = b->cache_lru & ~(1 << 15);
232 b->cache_lru = cache_lru;
239 u8 *hp = (
u8 *) h->alloc_arena;
245 static inline int BV (clib_bihash_bucket_is_empty)
246 (
BVT (clib_bihash_bucket) * b)
248 return b->as_u64 == 0;
256 hp = (
u8 *) h->alloc_arena;
265 void BV (clib_bihash_set_kvp_format_fn) (
BVT (clib_bihash) *
h,
271 BVT (clib_bihash_kv) * add_v,
int is_add);
272 int BV (clib_bihash_search) (
BVT (clib_bihash) *
h,
273 BVT (clib_bihash_kv) * search_v,
274 BVT (clib_bihash_kv) * return_v);
277 void *callback,
void *arg);
284 (
BVT (clib_bihash) *
h,
u64 hash,
BVT (clib_bihash_kv) * key_result)
287 BVT (clib_bihash_value) *
v;
288 BVT (clib_bihash_bucket) * b;
289 #if BIHASH_KVP_CACHE_SIZE > 0 290 BVT (clib_bihash_kv) * kvp;
294 bucket_index = hash & (h->nbuckets - 1);
295 b = &h->buckets[bucket_index];
300 #if BIHASH_KVP_CACHE_SIZE > 0 306 for (i = 0; i < limit; i++)
308 if (BV (clib_bihash_key_compare) (kvp[
i].key, key_result->key))
310 *key_result = kvp[
i];
318 hash >>= h->log2_nbuckets;
324 v += (b->linear_search == 0) ? hash & ((1 << b->log2_pages) - 1) : 0;
326 limit <<= b->log2_pages;
328 for (i = 0; i < limit; i++)
330 if (BV (clib_bihash_key_compare) (
v->kvp[
i].key, key_result->key))
332 *key_result =
v->kvp[
i];
334 #if BIHASH_KVP_CACHE_SIZE > 0 337 if (BV (clib_bihash_lock_bucket) (b))
339 cache_slot = BV (clib_bihash_get_lru) (b);
340 b->cache[cache_slot] =
v->kvp[
i];
341 BV (clib_bihash_update_lru) (b, cache_slot);
344 BV (clib_bihash_unlock_bucket) (b);
355 (
BVT (clib_bihash) *
h,
BVT (clib_bihash_kv) * key_result)
359 hash = BV (clib_bihash_hash) (key_result);
365 (
BVT (clib_bihash) *
h,
u64 hash)
368 BVT (clib_bihash_bucket) * b;
370 bucket_index = hash & (h->nbuckets - 1);
371 b = &h->buckets[bucket_index];
377 (
BVT (clib_bihash) *
h,
u64 hash)
380 BVT (clib_bihash_value) *
v;
381 BVT (clib_bihash_bucket) * b;
383 bucket_index = hash & (h->nbuckets - 1);
384 b = &h->buckets[bucket_index];
389 hash >>= h->log2_nbuckets;
392 v += (b->linear_search == 0) ? hash & ((1 << b->log2_pages) - 1) : 0;
397 static inline int BV (clib_bihash_search_inline_2_with_hash)
398 (
BVT (clib_bihash) *
h,
399 u64 hash,
BVT (clib_bihash_kv) * search_key,
BVT (clib_bihash_kv) * valuep)
402 BVT (clib_bihash_value) *
v;
403 BVT (clib_bihash_bucket) * b;
404 #if BIHASH_KVP_CACHE_SIZE > 0 405 BVT (clib_bihash_kv) * kvp;
411 bucket_index = hash & (h->nbuckets - 1);
412 b = &h->buckets[bucket_index];
418 #if BIHASH_KVP_CACHE_SIZE > 0 423 for (i = 0; i < limit; i++)
425 if (BV (clib_bihash_key_compare) (kvp[
i].key, search_key->key))
435 hash >>= h->log2_nbuckets;
440 v += (b->linear_search == 0) ? hash & ((1 << b->log2_pages) - 1) : 0;
442 limit <<= b->log2_pages;
444 for (i = 0; i < limit; i++)
446 if (BV (clib_bihash_key_compare) (
v->kvp[
i].key, search_key->key))
450 #if BIHASH_KVP_CACHE_SIZE > 0 454 if (BV (clib_bihash_lock_bucket) (b))
456 cache_slot = BV (clib_bihash_get_lru) (b);
457 b->cache[cache_slot] =
v->kvp[
i];
458 BV (clib_bihash_update_lru) (b, cache_slot);
461 BV (clib_bihash_unlock_bucket) (b);
472 (
BVT (clib_bihash) *
h,
473 BVT (clib_bihash_kv) * search_key,
BVT (clib_bihash_kv) * valuep)
477 hash = BV (clib_bihash_hash) (search_key);
479 return BV (clib_bihash_search_inline_2_with_hash) (
h, hash, search_key,
int clib_bihash_search_inline_with_hash(clib_bihash *h, u64 hash, clib_bihash_kv *in_out_kv)
Search a bi-hash table, use supplied hash code.
#define BIHASH_KVP_PER_PAGE
void clib_bihash_free(clib_bihash *h)
Destroy a bounded index extensible hash table.
Fixed length block allocator.
for(i=1;i<=collision_buckets;i++)
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
static uword clib_bihash_get_offset(clib_bihash *h, void *v)
Get clib mheap offset given a pointer.
int clib_bihash_search_inline(clib_bihash *h, clib_bihash_kv *in_out_kv)
Search a bi-hash table.
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
void clib_bihash_prefetch_bucket(clib_bihash *h, u64 hash)
Prefetch a bi-hash bucket given a hash code.
void clib_bihash_foreach_key_value_pair(clib_bihash *h, void *callback, void *arg)
Visit active (key,value) pairs in a bi-hash table.
#define CLIB_PREFETCH(addr, size, type)
void clib_bihash_prefetch_data(clib_bihash *h, u64 hash)
Prefetch bi-hash (key,value) data given a hash code.
int clib_bihash_search_inline_2(clib_bihash *h, clib_bihash_kv *search_key, clib_bihash_kv *valuep)
Search a bi-hash table.
template key/value backing page structure
struct clib_bihash_value offset
template key/value backing page structure
static void * clib_bihash_get_value(clib_bihash *h, uword offset)
Get pointer to value page given its clib mheap offset.
#define CLIB_CACHE_LINE_BYTES
#define STATIC_ASSERT_SIZEOF(d, s)
#define BIHASH_KVP_CACHE_SIZE