aboutsummaryrefslogtreecommitdiffstats
path: root/vppinfra/vppinfra/bihash_template.c
diff options
context:
space:
mode:
Diffstat (limited to 'vppinfra/vppinfra/bihash_template.c')
-rw-r--r--vppinfra/vppinfra/bihash_template.c455
1 files changed, 0 insertions, 455 deletions
diff --git a/vppinfra/vppinfra/bihash_template.c b/vppinfra/vppinfra/bihash_template.c
deleted file mode 100644
index 4b0b425788a..00000000000
--- a/vppinfra/vppinfra/bihash_template.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/** @cond DOCUMENTATION_IS_IN_BIHASH_DOC_H */
-
-void BV (clib_bihash_init)
- (BVT (clib_bihash) * h, char *name, u32 nbuckets, uword memory_size)
-{
- void *oldheap;
-
- nbuckets = 1 << (max_log2 (nbuckets));
-
- h->name = (u8 *) name;
- h->nbuckets = nbuckets;
- h->log2_nbuckets = max_log2 (nbuckets);
-
- h->mheap = mheap_alloc (0 /* use VM */ , memory_size);
-
- oldheap = clib_mem_set_heap (h->mheap);
- vec_validate_aligned (h->buckets, nbuckets - 1, CLIB_CACHE_LINE_BYTES);
- h->writer_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
- CLIB_CACHE_LINE_BYTES);
-
- clib_mem_set_heap (oldheap);
-}
-
-void BV (clib_bihash_free) (BVT (clib_bihash) * h)
-{
- mheap_free (h->mheap);
- memset (h, 0, sizeof (*h));
-}
-
-static
-BVT (clib_bihash_value) *
-BV (value_alloc) (BVT (clib_bihash) * h, u32 log2_pages)
-{
- BVT (clib_bihash_value) * rv = 0;
- void *oldheap;
-
- ASSERT (h->writer_lock[0]);
- if (log2_pages >= vec_len (h->freelists) || h->freelists[log2_pages] == 0)
- {
- oldheap = clib_mem_set_heap (h->mheap);
-
- vec_validate (h->freelists, log2_pages);
- vec_validate_aligned (rv, (1 << log2_pages) - 1, CLIB_CACHE_LINE_BYTES);
- clib_mem_set_heap (oldheap);
- goto initialize;
- }
- rv = h->freelists[log2_pages];
- h->freelists[log2_pages] = rv->next_free;
-
-initialize:
- ASSERT (rv);
- ASSERT (vec_len (rv) == (1 << log2_pages));
- /*
- * Latest gcc complains that the length arg is zero
- * if we replace (1<<log2_pages) with vec_len(rv).
- * No clue.
- */
- memset (rv, 0xff, sizeof (*rv) * (1 << log2_pages));
- return rv;
-}
-
-static void
-BV (value_free) (BVT (clib_bihash) * h, BVT (clib_bihash_value) * v)
-{
- u32 log2_pages;
-
- ASSERT (h->writer_lock[0]);
-
- log2_pages = min_log2 (vec_len (v));
-
- ASSERT (vec_len (h->freelists) > log2_pages);
-
- v->next_free = h->freelists[log2_pages];
- h->freelists[log2_pages] = v;
-}
-
-static inline void
-BV (make_working_copy) (BVT (clib_bihash) * h, clib_bihash_bucket_t * b)
-{
- BVT (clib_bihash_value) * v;
- clib_bihash_bucket_t working_bucket __attribute__ ((aligned (8)));
- void *oldheap;
- BVT (clib_bihash_value) * working_copy;
- u32 cpu_number = os_get_cpu_number ();
-
- if (cpu_number >= vec_len (h->working_copies))
- {
- oldheap = clib_mem_set_heap (h->mheap);
- vec_validate (h->working_copies, cpu_number);
- clib_mem_set_heap (oldheap);
- }
-
- /*
- * working_copies are per-cpu so that near-simultaneous
- * updates from multiple threads will not result in sporadic, spurious
- * lookup failures.
- */
- working_copy = h->working_copies[cpu_number];
-
- h->saved_bucket.as_u64 = b->as_u64;
- oldheap = clib_mem_set_heap (h->mheap);
-
- if ((1 << b->log2_pages) > vec_len (working_copy))
- {
- vec_validate_aligned (working_copy, (1 << b->log2_pages) - 1,
- sizeof (u64));
- h->working_copies[cpu_number] = working_copy;
- }
-
- _vec_len (working_copy) = 1 << b->log2_pages;
- clib_mem_set_heap (oldheap);
-
- v = BV (clib_bihash_get_value) (h, b->offset);
-
- clib_memcpy (working_copy, v, sizeof (*v) * (1 << b->log2_pages));
- working_bucket.as_u64 = b->as_u64;
- working_bucket.offset = BV (clib_bihash_get_offset) (h, working_copy);
- CLIB_MEMORY_BARRIER ();
- b->as_u64 = working_bucket.as_u64;
- h->working_copies[cpu_number] = working_copy;
-}
-
-static
-BVT (clib_bihash_value) *
-BV (split_and_rehash)
- (BVT (clib_bihash) * h,
- BVT (clib_bihash_value) * old_values, u32 new_log2_pages)
-{
- BVT (clib_bihash_value) * new_values, *v, *new_v;
- int i, j, k;
-
- new_values = BV (value_alloc) (h, new_log2_pages);
-
- v = old_values;
- for (i = 0; i < vec_len (old_values); i++)
- {
- u64 new_hash;
-
- for (j = 0; j < BIHASH_KVP_PER_PAGE; j++)
- {
- if (BV (clib_bihash_is_free) (&(v->kvp[j])) == 0)
- {
- new_hash = BV (clib_bihash_hash) (&(v->kvp[j]));
- new_hash >>= h->log2_nbuckets;
- new_hash &= (1 << new_log2_pages) - 1;
-
- new_v = &new_values[new_hash];
-
- for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
- {
- if (BV (clib_bihash_is_free) (&(new_v->kvp[k])))
- {
- clib_memcpy (&(new_v->kvp[k]), &(v->kvp[j]),
- sizeof (new_v->kvp[k]));
- goto doublebreak;
- }
- }
- /* Crap. Tell caller to try again */
- BV (value_free) (h, new_values);
- return 0;
- }
- doublebreak:
- ;
- }
- v++;
- }
- return new_values;
-}
-
-int BV (clib_bihash_add_del)
- (BVT (clib_bihash) * h, BVT (clib_bihash_kv) * add_v, int is_add)
-{
- u32 bucket_index;
- clib_bihash_bucket_t *b, tmp_b;
- BVT (clib_bihash_value) * v, *new_v, *save_new_v, *working_copy;
- u32 value_index;
- int rv = 0;
- int i;
- u64 hash, new_hash;
- u32 new_log2_pages;
- u32 cpu_number = os_get_cpu_number ();
-
- hash = BV (clib_bihash_hash) (add_v);
-
- bucket_index = hash & (h->nbuckets - 1);
- b = &h->buckets[bucket_index];
-
- hash >>= h->log2_nbuckets;
-
- while (__sync_lock_test_and_set (h->writer_lock, 1))
- ;
-
- /* First elt in the bucket? */
- if (b->offset == 0)
- {
- if (is_add == 0)
- {
- rv = -1;
- goto unlock;
- }
-
- v = BV (value_alloc) (h, 0);
- *v->kvp = *add_v;
- tmp_b.as_u64 = 0;
- tmp_b.offset = BV (clib_bihash_get_offset) (h, v);
-
- b->as_u64 = tmp_b.as_u64;
- goto unlock;
- }
-
- BV (make_working_copy) (h, b);
-
- v = BV (clib_bihash_get_value) (h, h->saved_bucket.offset);
- value_index = hash & ((1 << h->saved_bucket.log2_pages) - 1);
- v += value_index;
-
- if (is_add)
- {
- /*
- * For obvious (in hindsight) reasons, see if we're supposed to
- * replace an existing key, then look for an empty slot.
- */
- for (i = 0; i < BIHASH_KVP_PER_PAGE; i++)
- {
- if (!memcmp (&(v->kvp[i]), &add_v->key, sizeof (add_v->key)))
- {
- clib_memcpy (&(v->kvp[i]), add_v, sizeof (*add_v));
- CLIB_MEMORY_BARRIER ();
- /* Restore the previous (k,v) pairs */
- b->as_u64 = h->saved_bucket.as_u64;
- goto unlock;
- }
- }
- for (i = 0; i < BIHASH_KVP_PER_PAGE; i++)
- {
- if (BV (clib_bihash_is_free) (&(v->kvp[i])))
- {
- clib_memcpy (&(v->kvp[i]), add_v, sizeof (*add_v));
- CLIB_MEMORY_BARRIER ();
- b->as_u64 = h->saved_bucket.as_u64;
- goto unlock;
- }
- }
- /* no room at the inn... split case... */
- }
- else
- {
- for (i = 0; i < BIHASH_KVP_PER_PAGE; i++)
- {
- if (!memcmp (&(v->kvp[i]), &add_v->key, sizeof (add_v->key)))
- {
- memset (&(v->kvp[i]), 0xff, sizeof (*(add_v)));
- CLIB_MEMORY_BARRIER ();
- b->as_u64 = h->saved_bucket.as_u64;
- goto unlock;
- }
- }
- rv = -3;
- b->as_u64 = h->saved_bucket.as_u64;
- goto unlock;
- }
-
- new_log2_pages = h->saved_bucket.log2_pages + 1;
-
-expand_again:
- working_copy = h->working_copies[cpu_number];
- new_v = BV (split_and_rehash) (h, working_copy, new_log2_pages);
- if (new_v == 0)
- {
- new_log2_pages++;
- goto expand_again;
- }
-
- /* Try to add the new entry */
- save_new_v = new_v;
- new_hash = BV (clib_bihash_hash) (add_v);
- new_hash >>= h->log2_nbuckets;
- new_hash &= (1 << min_log2 (vec_len (new_v))) - 1;
- new_v += new_hash;
-
- for (i = 0; i < BIHASH_KVP_PER_PAGE; i++)
- {
- if (BV (clib_bihash_is_free) (&(new_v->kvp[i])))
- {
- clib_memcpy (&(new_v->kvp[i]), add_v, sizeof (*add_v));
- goto expand_ok;
- }
- }
- /* Crap. Try again */
- new_log2_pages++;
- BV (value_free) (h, save_new_v);
- goto expand_again;
-
-expand_ok:
- tmp_b.log2_pages = min_log2 (vec_len (save_new_v));
- tmp_b.offset = BV (clib_bihash_get_offset) (h, save_new_v);
- CLIB_MEMORY_BARRIER ();
- b->as_u64 = tmp_b.as_u64;
- v = BV (clib_bihash_get_value) (h, h->saved_bucket.offset);
- BV (value_free) (h, v);
-
-unlock:
- CLIB_MEMORY_BARRIER ();
- h->writer_lock[0] = 0;
- return rv;
-}
-
-int BV (clib_bihash_search)
- (const BVT (clib_bihash) * h,
- BVT (clib_bihash_kv) * search_key, BVT (clib_bihash_kv) * valuep)
-{
- u64 hash;
- u32 bucket_index;
- uword value_index;
- BVT (clib_bihash_value) * v;
- clib_bihash_bucket_t *b;
- int i;
-
- ASSERT (valuep);
-
- hash = BV (clib_bihash_hash) (search_key);
-
- bucket_index = hash & (h->nbuckets - 1);
- b = &h->buckets[bucket_index];
-
- if (b->offset == 0)
- return -1;
-
- hash >>= h->log2_nbuckets;
-
- v = BV (clib_bihash_get_value) (h, b->offset);
- value_index = hash & ((1 << b->log2_pages) - 1);
- v += value_index;
-
- for (i = 0; i < BIHASH_KVP_PER_PAGE; i++)
- {
- if (BV (clib_bihash_key_compare) (v->kvp[i].key, search_key->key))
- {
- *valuep = v->kvp[i];
- return 0;
- }
- }
- return -1;
-}
-
-u8 *BV (format_bihash) (u8 * s, va_list * args)
-{
- BVT (clib_bihash) * h = va_arg (*args, BVT (clib_bihash) *);
- int verbose = va_arg (*args, int);
- clib_bihash_bucket_t *b;
- BVT (clib_bihash_value) * v;
- int i, j, k;
- u64 active_elements = 0;
-
- s = format (s, "Hash table %s\n", h->name ? h->name : (u8 *) "(unnamed)");
-
- for (i = 0; i < h->nbuckets; i++)
- {
- b = &h->buckets[i];
- if (b->offset == 0)
- {
- if (verbose > 1)
- s = format (s, "[%d]: empty\n", i);
- continue;
- }
-
- if (verbose)
- {
- s = format (s, "[%d]: heap offset %d, len %d\n", i,
- b->offset, (1 << b->log2_pages));
- }
-
- v = BV (clib_bihash_get_value) (h, b->offset);
- for (j = 0; j < (1 << b->log2_pages); j++)
- {
- for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
- {
- if (BV (clib_bihash_is_free) (&v->kvp[k]))
- {
- if (verbose > 1)
- s = format (s, " %d: empty\n",
- j * BIHASH_KVP_PER_PAGE + k);
- continue;
- }
- if (verbose)
- {
- s = format (s, " %d: %U\n",
- j * BIHASH_KVP_PER_PAGE + k,
- BV (format_bihash_kvp), &(v->kvp[k]));
- }
- active_elements++;
- }
- v++;
- }
- }
-
- s = format (s, " %lld active elements\n", active_elements);
- s = format (s, " %d free lists\n", vec_len (h->freelists));
-
- return s;
-}
-
-void BV (clib_bihash_foreach_key_value_pair)
- (BVT (clib_bihash) * h, void *callback, void *arg)
-{
- int i, j, k;
- clib_bihash_bucket_t *b;
- BVT (clib_bihash_value) * v;
- void (*fp) (BVT (clib_bihash_kv) *, void *) = callback;
-
- for (i = 0; i < h->nbuckets; i++)
- {
- b = &h->buckets[i];
- if (b->offset == 0)
- continue;
-
- v = BV (clib_bihash_get_value) (h, b->offset);
- for (j = 0; j < (1 << b->log2_pages); j++)
- {
- for (k = 0; k < BIHASH_KVP_PER_PAGE; k++)
- {
- if (BV (clib_bihash_is_free) (&v->kvp[k]))
- continue;
-
- (*fp) (&v->kvp[k], arg);
- }
- v++;
- }
- }
-}
-
-/** @endcond */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */