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);
77 BVT (clib_bihash_value) * values;
78 BVT (clib_bihash_bucket) * buckets;
79 volatile u32 *writer_lock;
81 BVT (clib_bihash_value) ** working_copies;
82 int *working_copy_lengths;
83 BVT (clib_bihash_bucket) saved_bucket;
92 BVT (clib_bihash_value) ** freelists;
99 uword alloc_arena_next;
100 uword alloc_arena_size;
111 BV (clib_bihash_update_lru) (
BVT (clib_bihash_bucket) * b,
u8 slot)
113 #if BIHASH_KVP_CACHE_SIZE > 1 114 u16 value, tmp, mask;
131 value = b->cache_lru;
138 found_lru_pos = ((tmp & (7 << 3)) == 0) ? 1 : 0;
140 found_lru_pos = ((tmp & (7 << 6)) == 0) ? 2 : found_lru_pos;
142 found_lru_pos = ((tmp & (7 << 9)) == 0) ? 3 : found_lru_pos;
144 found_lru_pos = ((tmp & (7 << 12)) == 0) ? 4 : found_lru_pos;
149 mask = 0xFFFF << found_lru_pos;
150 mask <<= found_lru_pos;
151 mask <<= found_lru_pos;
158 save_hi = value & mask;
160 value = save_hi | (tmp << 3) | slot;
162 b->cache_lru = value;
167 BV (clib_bihash_update_lru_not_inline) (
BVT (clib_bihash_bucket) * b,
170 static inline u8 BV (clib_bihash_get_lru) (
BVT (clib_bihash_bucket) * b)
172 #if BIHASH_KVP_CACHE_SIZE > 0 179 static inline void BV (clib_bihash_reset_cache) (
BVT (clib_bihash_bucket) * b)
181 #if BIHASH_KVP_CACHE_SIZE > 0 182 u16 initial_lru_value;
184 memset (b->cache, 0xff, sizeof (b->cache));
191 initial_lru_value = 0;
193 initial_lru_value = (0 << 3) | (1 << 0);
195 initial_lru_value = (0 << 6) | (1 << 3) | (2 << 0);
197 initial_lru_value = (0 << 9) | (1 << 6) | (2 << 3) | (3 << 0);
199 initial_lru_value = (0 << 12) | (1 << 9) | (2 << 6) | (3 << 3) | (4 << 0);
201 b->cache_lru = initial_lru_value;
205 static inline int BV (clib_bihash_lock_bucket) (
BVT (clib_bihash_bucket) * b)
207 #if BIHASH_KVP_CACHE_SIZE > 0 211 cache_lru_bit = 1 << 15;
213 rv = __sync_fetch_and_or (&b->cache_lru, cache_lru_bit);
221 static inline void BV (clib_bihash_unlock_bucket)
222 (
BVT (clib_bihash_bucket) * b)
224 #if BIHASH_KVP_CACHE_SIZE > 0 227 cache_lru = b->cache_lru & ~(1 << 15);
228 b->cache_lru = cache_lru;
235 u8 *hp = (
u8 *) h->alloc_arena;
246 hp = (
u8 *) h->alloc_arena;
255 void BV (clib_bihash_set_kvp_format_fn) (
BVT (clib_bihash) *
h,
261 BVT (clib_bihash_kv) * add_v,
int is_add);
262 int BV (clib_bihash_search) (
BVT (clib_bihash) *
h,
263 BVT (clib_bihash_kv) * search_v,
264 BVT (clib_bihash_kv) * return_v);
267 void *callback,
void *arg);
274 (
BVT (clib_bihash) *
h,
u64 hash,
BVT (clib_bihash_kv) * key_result)
277 BVT (clib_bihash_value) *
v;
278 BVT (clib_bihash_bucket) * b;
279 #if BIHASH_KVP_CACHE_SIZE > 0 280 BVT (clib_bihash_kv) * kvp;
284 bucket_index = hash & (h->nbuckets - 1);
285 b = &h->buckets[bucket_index];
290 #if BIHASH_KVP_CACHE_SIZE > 0 296 for (i = 0; i < limit; i++)
298 if (BV (clib_bihash_key_compare) (kvp[
i].key, key_result->key))
300 *key_result = kvp[
i];
308 hash >>= h->log2_nbuckets;
314 v += (b->linear_search == 0) ? hash & ((1 << b->log2_pages) - 1) : 0;
316 limit <<= b->log2_pages;
318 for (i = 0; i < limit; i++)
320 if (BV (clib_bihash_key_compare) (
v->kvp[
i].key, key_result->key))
322 *key_result =
v->kvp[
i];
324 #if BIHASH_KVP_CACHE_SIZE > 0 327 if (BV (clib_bihash_lock_bucket) (b))
329 cache_slot = BV (clib_bihash_get_lru) (b);
330 b->cache[cache_slot] =
v->kvp[
i];
331 BV (clib_bihash_update_lru) (b, cache_slot);
334 BV (clib_bihash_unlock_bucket) (b);
345 (
BVT (clib_bihash) *
h,
BVT (clib_bihash_kv) * key_result)
349 hash = BV (clib_bihash_hash) (key_result);
355 (
BVT (clib_bihash) *
h,
u64 hash)
358 BVT (clib_bihash_bucket) * b;
360 bucket_index = hash & (h->nbuckets - 1);
361 b = &h->buckets[bucket_index];
367 (
BVT (clib_bihash) *
h,
u64 hash)
370 BVT (clib_bihash_value) *
v;
371 BVT (clib_bihash_bucket) * b;
373 bucket_index = hash & (h->nbuckets - 1);
374 b = &h->buckets[bucket_index];
379 hash >>= h->log2_nbuckets;
382 v += (b->linear_search == 0) ? hash & ((1 << b->log2_pages) - 1) : 0;
387 static inline int BV (clib_bihash_search_inline_2_with_hash)
388 (
BVT (clib_bihash) *
h,
389 u64 hash,
BVT (clib_bihash_kv) * search_key,
BVT (clib_bihash_kv) * valuep)
392 BVT (clib_bihash_value) *
v;
393 BVT (clib_bihash_bucket) * b;
394 #if BIHASH_KVP_CACHE_SIZE > 0 395 BVT (clib_bihash_kv) * kvp;
401 bucket_index = hash & (h->nbuckets - 1);
402 b = &h->buckets[bucket_index];
408 #if BIHASH_KVP_CACHE_SIZE > 0 413 for (i = 0; i < limit; i++)
415 if (BV (clib_bihash_key_compare) (kvp[
i].key, search_key->key))
425 hash >>= h->log2_nbuckets;
430 v += (b->linear_search == 0) ? hash & ((1 << b->log2_pages) - 1) : 0;
432 limit <<= b->log2_pages;
434 for (i = 0; i < limit; i++)
436 if (BV (clib_bihash_key_compare) (
v->kvp[
i].key, search_key->key))
440 #if BIHASH_KVP_CACHE_SIZE > 0 444 if (BV (clib_bihash_lock_bucket) (b))
446 cache_slot = BV (clib_bihash_get_lru) (b);
447 b->cache[cache_slot] =
v->kvp[
i];
448 BV (clib_bihash_update_lru) (b, cache_slot);
451 BV (clib_bihash_unlock_bucket) (b);
462 (
BVT (clib_bihash) *
h,
463 BVT (clib_bihash_kv) * search_key,
BVT (clib_bihash_kv) * valuep)
467 hash = BV (clib_bihash_hash) (search_key);
469 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 BIHASH_KVP_CACHE_SIZE