17 (
BVT(clib_bihash) * h,
char * name,
u32 nbuckets,
22 nbuckets = 1 << (
max_log2 (nbuckets));
25 h->nbuckets = nbuckets;
26 h->log2_nbuckets =
max_log2 (nbuckets);
41 memset (h, 0,
sizeof (*h));
44 static BVT(clib_bihash_value) *
45 BV(value_alloc) (
BVT(clib_bihash) * h,
u32 log2_pages)
47 BVT(clib_bihash_value) * rv = 0;
50 ASSERT (h->writer_lock[0]);
51 if (log2_pages >=
vec_len (h->freelists)
52 || h->freelists [log2_pages] == 0)
61 rv = h->freelists[log2_pages];
62 h->freelists[log2_pages] = rv->next_free;
72 memset (rv, 0xff,
sizeof (*rv) * (1<<log2_pages));
78 (
BVT(clib_bihash) * h,
79 BVT(clib_bihash_value) * v)
83 ASSERT (h->writer_lock[0]);
89 v->next_free = h->freelists[log2_pages];
90 h->freelists[log2_pages] = v;
97 BVT(clib_bihash_value) * v;
100 BVT(clib_bihash_value) * working_copy;
103 if (cpu_number >=
vec_len (h->working_copies))
115 working_copy = h->working_copies[cpu_number];
117 h->saved_bucket.as_u64 = b->as_u64;
120 if ((1<<b->log2_pages) >
vec_len (working_copy))
124 h->working_copies[cpu_number] = working_copy;
127 _vec_len(working_copy) = 1<<b->log2_pages;
132 clib_memcpy (working_copy, v,
sizeof (*v)*(1<<b->log2_pages));
133 working_bucket.as_u64 = b->as_u64;
136 b->as_u64 = working_bucket.as_u64;
137 h->working_copies[cpu_number] = working_copy;
140 static BVT(clib_bihash_value) *
142 (
BVT(clib_bihash) * h,
143 BVT(clib_bihash_value) * old_values,
146 BVT(clib_bihash_value) * new_values, * v, * new_v;
149 new_values =
BV(value_alloc) (h, new_log2_pages);
152 for (i = 0; i <
vec_len (old_values); i++)
158 if (
BV(clib_bihash_is_free)(&(v->kvp[j])) == 0)
160 new_hash =
BV(clib_bihash_hash) (&(v->kvp[j]));
161 new_hash >>= h->log2_nbuckets;
162 new_hash &= (1<<new_log2_pages) - 1;
164 new_v = &new_values [new_hash];
168 if (
BV(clib_bihash_is_free)(&(new_v->kvp[k])))
171 sizeof (new_v->kvp[k]));
176 BV(value_free) (h, new_values);
189 BVT(clib_bihash_kv) * add_v,
194 BVT(clib_bihash_value) * v, * new_v, * save_new_v, * working_copy;
202 hash =
BV(clib_bihash_hash) (add_v);
204 bucket_index = hash & (h->nbuckets-1);
205 b = &h->buckets[bucket_index];
207 hash >>= h->log2_nbuckets;
209 while (__sync_lock_test_and_set (h->writer_lock, 1))
221 v =
BV(value_alloc) (h, 0);
233 value_index = hash & ((1<<h->saved_bucket.log2_pages)-1);
244 if (!memcmp(&(v->kvp[i]), &add_v->key, sizeof (add_v->key)))
246 clib_memcpy (&(v->kvp[i]), add_v, sizeof (*add_v));
249 b->as_u64 = h->saved_bucket.as_u64;
255 if (
BV(clib_bihash_is_free)(&(v->kvp[i])))
257 clib_memcpy (&(v->kvp[i]), add_v, sizeof (*add_v));
259 b->as_u64 = h->saved_bucket.as_u64;
269 if (!memcmp(&(v->kvp[i]), &add_v->key, sizeof (add_v->key)))
271 memset (&(v->kvp[i]), 0xff, sizeof (*(add_v)));
273 b->as_u64 = h->saved_bucket.as_u64;
278 b->as_u64 = h->saved_bucket.as_u64;
282 new_log2_pages = h->saved_bucket.log2_pages + 1;
285 working_copy = h->working_copies[cpu_number];
295 new_hash =
BV(clib_bihash_hash) (add_v);
296 new_hash >>= h->log2_nbuckets;
302 if (
BV(clib_bihash_is_free)(&(new_v->kvp[
i])))
304 clib_memcpy (&(new_v->kvp[i]), add_v, sizeof (*add_v));
310 BV(value_free) (h, save_new_v);
319 BV(value_free) (h, v);
323 h->writer_lock[0] = 0;
329 BVT(clib_bihash_kv) *search_key,
330 BVT(clib_bihash_kv) *valuep)
335 BVT(clib_bihash_value) * v;
341 hash =
BV(clib_bihash_hash) (search_key);
343 bucket_index = hash & (h->nbuckets-1);
344 b = &h->buckets[bucket_index];
349 hash >>= h->log2_nbuckets;
352 value_index = hash & ((1<<b->log2_pages)-1);
357 if (
BV(clib_bihash_key_compare)(v->kvp[i].key, search_key->key))
369 = va_arg (*args,
BVT(clib_bihash) *);
370 int verbose = va_arg (*args,
int);
372 BVT(clib_bihash_value) * v;
374 u64 active_elements = 0;
376 s =
format (s,
"Hash table %s\n", h->name ? h->name : (
u8 *)
"(unnamed)");
378 for (i = 0; i < h->nbuckets; i++)
384 s =
format (s,
"[%d]: empty\n", i);
390 s =
format (s,
"[%d]: heap offset %d, len %d\n", i,
399 if (
BV(clib_bihash_is_free)(&v->kvp[k]))
402 s =
format (s,
" %d: empty\n",
403 j * BIHASH_KVP_PER_PAGE + k);
408 s =
format (s,
" %d: %U\n",
409 j * BIHASH_KVP_PER_PAGE + k,
410 BV(format_bihash_kvp),
419 s =
format (s,
" %lld active elements\n", active_elements);
433 BVT(clib_bihash_value) * v;
434 void (*fp)(
BVT(clib_bihash_kv) *,
void *) = callback;
436 for (i = 0; i < h->nbuckets; i++)
447 if (
BV(clib_bihash_is_free)(&v->kvp[k]))
450 (*fp)(&v->kvp[k], arg);
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
sll srl srl sll sra u16x4 i
static void(BVT(clib_bihash)*h, BVT(clib_bihash_value)*v)
void * mheap_alloc(void *memory, uword size)
always_inline uword max_log2(uword x)
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
int BV() clib_bihash_add_del(BVT(clib_bihash)*h, BVT(clib_bihash_kv)*add_v, int is_add)
u8 * format_mheap(u8 *s, va_list *va)
void BV() clib_bihash_foreach_key_value_pair(BVT(clib_bihash)*h, void *callback, void *arg)
static BVT(clib_bihash_value)
void BV() clib_bihash_init(BVT(clib_bihash)*h, char *name, u32 nbuckets, uword memory_size)
int BV() clib_bihash_search(BVT(clib_bihash)*h, BVT(clib_bihash_kv)*search_key, BVT(clib_bihash_kv)*valuep)
always_inline void * clib_mem_alloc_aligned(uword size, uword align)
#define BIHASH_KVP_PER_PAGE
uword os_get_cpu_number(void)
static uword BV() clib_bihash_get_offset(BVT(clib_bihash)*h, void *v)
always_inline void * clib_mem_set_heap(void *heap)
u8 *BV() format_bihash(u8 *s, va_list *args)
#define clib_memcpy(a, b, c)
static void make_working_copy(vnet_classify_table_t *t, vnet_classify_bucket_t *b)
void BV() clib_bihash_free(BVT(clib_bihash)*h)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void *BV() clib_bihash_get_value(BVT(clib_bihash)*h, uword offset)
always_inline uword min_log2(uword x)
#define CLIB_MEMORY_BARRIER()
#define CLIB_CACHE_LINE_BYTES
static vnet_classify_entry_t * split_and_rehash(vnet_classify_table_t *t, vnet_classify_entry_t *old_values, u32 new_log2_pages)