summaryrefslogtreecommitdiffstats
path: root/src/vppinfra
diff options
context:
space:
mode:
Diffstat (limited to 'src/vppinfra')
-rw-r--r--src/vppinfra/CMakeLists.txt1
-rw-r--r--src/vppinfra/bihash_all_vector.c58
-rw-r--r--src/vppinfra/bihash_template.c74
-rw-r--r--src/vppinfra/bihash_template.h14
4 files changed, 136 insertions, 11 deletions
diff --git a/src/vppinfra/CMakeLists.txt b/src/vppinfra/CMakeLists.txt
index a42bcb818a5..d8b302cf399 100644
--- a/src/vppinfra/CMakeLists.txt
+++ b/src/vppinfra/CMakeLists.txt
@@ -40,6 +40,7 @@ install(
##############################################################################
set(VPPINFRA_SRCS
backtrace.c
+ bihash_all_vector.c
cpu.c
cuckoo_template.c
elf.c
diff --git a/src/vppinfra/bihash_all_vector.c b/src/vppinfra/bihash_all_vector.c
new file mode 100644
index 00000000000..b6c64a30e0b
--- /dev/null
+++ b/src/vppinfra/bihash_all_vector.c
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#include <vppinfra/mem.h>
+
+/* Vector of all bihashes */
+void **clib_all_bihashes;
+static void **clib_all_bihash_heap;
+
+void *
+clib_all_bihash_set_heap (void)
+{
+ if (PREDICT_FALSE (clib_all_bihash_heap == 0))
+ clib_all_bihash_heap = clib_mem_get_heap ();
+
+ return clib_mem_set_heap (clib_all_bihash_heap);
+}
+
+/*
+ * Leave it to Beaver to change the size of a bihash
+ * by making a clone in a stack local and then copying it...
+ */
+void
+clib_bihash_copied (void *dst, void *src)
+{
+ int i;
+
+ for (i = 0; i < vec_len (clib_all_bihashes); i++)
+ {
+ if (clib_all_bihashes[i] == src)
+ {
+ clib_all_bihashes[i] = dst;
+ return;
+ }
+ }
+ clib_warning ("Couldn't find bihash copy source %llx!", src);
+}
+
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vppinfra/bihash_template.c b/src/vppinfra/bihash_template.c
index a10dee025bf..bf6be83b2e0 100644
--- a/src/vppinfra/bihash_template.c
+++ b/src/vppinfra/bihash_template.c
@@ -32,17 +32,33 @@ static inline void *BV (alloc_aligned) (BVT (clib_bihash) * h, uword nbytes)
return (void *) (uword) (rv + alloc_arena (h));
}
+void BV (clib_bihash_instantiate) (BVT (clib_bihash) * h)
+{
+ uword bucket_size;
+
+ alloc_arena (h) = (uword) clib_mem_vm_alloc (h->memory_size);
+ alloc_arena_next (h) = 0;
+ alloc_arena_size (h) = h->memory_size;
+
+ bucket_size = h->nbuckets * sizeof (h->buckets[0]);
+ h->buckets = BV (alloc_aligned) (h, bucket_size);
+
+ h->alloc_lock = BV (alloc_aligned) (h, CLIB_CACHE_LINE_BYTES);
+ h->alloc_lock[0] = 0;
+}
void BV (clib_bihash_init)
(BVT (clib_bihash) * h, char *name, u32 nbuckets, uword memory_size)
{
- uword bucket_size;
-
+ int i;
+ void *oldheap;
nbuckets = 1 << (max_log2 (nbuckets));
h->name = (u8 *) name;
h->nbuckets = nbuckets;
h->log2_nbuckets = max_log2 (nbuckets);
+ h->memory_size = memory_size;
+ alloc_arena (h) = 0;
/*
* Make sure the requested size is rational. The max table
@@ -51,18 +67,21 @@ void BV (clib_bihash_init)
* the offset by CLIB_LOG2_CACHE_LINE_BYTES...
*/
ASSERT (memory_size < (1ULL << BIHASH_BUCKET_OFFSET_BITS));
+ h->fmt_fn = NULL;
- alloc_arena (h) = (uword) clib_mem_vm_alloc (memory_size);
- alloc_arena_next (h) = 0;
- alloc_arena_size (h) = memory_size;
+ /* Add this hash table to the list */
+ for (i = 0; i < vec_len (clib_all_bihashes); i++)
+ if (clib_all_bihashes[i] == h)
+ return;
- bucket_size = nbuckets * sizeof (h->buckets[0]);
- h->buckets = BV (alloc_aligned) (h, bucket_size);
+ /* Unfortunately, the heap push/pop is required.... */
+ oldheap = clib_all_bihash_set_heap ();
+ vec_add1 (clib_all_bihashes, (void *) h);
+ clib_mem_set_heap (oldheap);
- h->alloc_lock = BV (alloc_aligned) (h, CLIB_CACHE_LINE_BYTES);
- h->alloc_lock[0] = 0;
-
- h->fmt_fn = NULL;
+#if BIHASH_INSTANTIATE_IMMEDIATELY
+ BV (clib_bihash_instantiate) (h);
+#endif
}
#if BIHASH_32_64_SVM
@@ -195,6 +214,11 @@ void BV (clib_bihash_set_kvp_format_fn) (BVT (clib_bihash) * h,
void BV (clib_bihash_free) (BVT (clib_bihash) * h)
{
+ int i;
+
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ goto never_initialized;
+
vec_free (h->working_copies);
vec_free (h->working_copy_lengths);
#if BIHASH_32_64_SVM == 0
@@ -204,7 +228,18 @@ void BV (clib_bihash_free) (BVT (clib_bihash) * h)
(void) close (h->memfd);
#endif
clib_mem_vm_free ((void *) (uword) (alloc_arena (h)), alloc_arena_size (h));
+never_initialized:
clib_memset (h, 0, sizeof (*h));
+ for (i = 0; i < vec_len (clib_all_bihashes); i++)
+ {
+ if ((void *) h == clib_all_bihashes[i])
+ {
+ vec_delete (clib_all_bihashes, 1, i);
+ return;
+ }
+ }
+ clib_warning ("Couldn't find hash table %llx on clib_all_bihashes...",
+ (u64) h);
}
static
@@ -417,6 +452,14 @@ static inline int BV (clib_bihash_add_del_inline)
int mark_bucket_linear;
int resplit_once;
+ /* Create the table (is_add=1), or flunk the request now (is_add=0) */
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ {
+ if (is_add == 0)
+ return (-1);
+ BV (clib_bihash_instantiate) (h);
+ }
+
hash = BV (clib_bihash_hash) (add_v);
bucket_index = hash & (h->nbuckets - 1);
@@ -678,6 +721,9 @@ int BV (clib_bihash_search)
ASSERT (valuep);
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ return -1;
+
hash = BV (clib_bihash_hash) (search_key);
bucket_index = hash & (h->nbuckets - 1);
@@ -726,6 +772,9 @@ u8 *BV (format_bihash) (u8 * s, va_list * args)
s = format (s, "Hash table %s\n", h->name ? h->name : (u8 *) "(unnamed)");
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ return format (s, "[empty, uninitialized]");
+
for (i = 0; i < h->nbuckets; i++)
{
b = &h->buckets[i];
@@ -820,6 +869,9 @@ void BV (clib_bihash_foreach_key_value_pair)
BVT (clib_bihash_value) * v;
void (*fp) (BVT (clib_bihash_kv) *, void *) = callback;
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ return;
+
for (i = 0; i < h->nbuckets; i++)
{
b = &h->buckets[i];
diff --git a/src/vppinfra/bihash_template.h b/src/vppinfra/bihash_template.h
index d145b61952a..2e2ba911b7c 100644
--- a/src/vppinfra/bihash_template.h
+++ b/src/vppinfra/bihash_template.h
@@ -129,6 +129,7 @@ BVS (clib_bihash)
u32 nbuckets;
u32 log2_nbuckets;
+ u64 memory_size;
u8 *name;
u64 *freelists;
@@ -157,6 +158,8 @@ BVS (clib_bihash)
} BVT (clib_bihash);
+extern void **clib_all_bihashes;
+
#if BIHASH_32_64_SVM
#undef alloc_arena_next
#undef alloc_arena_size
@@ -313,6 +316,8 @@ int BV (clib_bihash_search) (BVT (clib_bihash) * h,
void BV (clib_bihash_foreach_key_value_pair) (BVT (clib_bihash) * h,
void *callback, void *arg);
+void *clib_all_bihash_set_heap (void);
+void clib_bihash_copied (void *dst, void *src);
format_function_t BV (format_bihash);
format_function_t BV (format_bihash_kvp);
@@ -326,6 +331,9 @@ static inline int BV (clib_bihash_search_inline_with_hash)
BVT (clib_bihash_bucket) * b;
int i, limit;
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ return -1;
+
bucket_index = hash & (h->nbuckets - 1);
b = &h->buckets[bucket_index];
@@ -389,6 +397,9 @@ static inline void BV (clib_bihash_prefetch_data)
BVT (clib_bihash_value) * v;
BVT (clib_bihash_bucket) * b;
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ return;
+
bucket_index = hash & (h->nbuckets - 1);
b = &h->buckets[bucket_index];
@@ -414,6 +425,9 @@ static inline int BV (clib_bihash_search_inline_2_with_hash)
ASSERT (valuep);
+ if (PREDICT_FALSE (alloc_arena (h) == 0))
+ return -1;
+
bucket_index = hash & (h->nbuckets - 1);
b = &h->buckets[bucket_index];