summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vppinfra/bihash_template.c31
-rw-r--r--src/vppinfra/bihash_template.h1
2 files changed, 25 insertions, 7 deletions
diff --git a/src/vppinfra/bihash_template.c b/src/vppinfra/bihash_template.c
index 11e3ac448f8..4ef32efbe89 100644
--- a/src/vppinfra/bihash_template.c
+++ b/src/vppinfra/bihash_template.c
@@ -42,9 +42,8 @@ void BV (clib_bihash_instantiate) (BVT (clib_bihash) * h)
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;
+ CLIB_MEMORY_BARRIER ();
+ h->instantiated = 1;
}
void BV (clib_bihash_init)
@@ -58,6 +57,7 @@ void BV (clib_bihash_init)
h->nbuckets = nbuckets;
h->log2_nbuckets = max_log2 (nbuckets);
h->memory_size = memory_size;
+ h->instantiated = 0;
alloc_arena (h) = 0;
/*
@@ -79,6 +79,15 @@ void BV (clib_bihash_init)
vec_add1 (clib_all_bihashes, (void *) h);
clib_mem_set_heap (oldheap);
+
+ /*
+ * Set up the lock now, so we can use it to make the first add
+ * thread-safe
+ */
+ h->alloc_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
+ CLIB_CACHE_LINE_BYTES);
+ h->alloc_lock[0] = 0;
+
#if BIHASH_INSTANTIATE_IMMEDIATELY
BV (clib_bihash_instantiate) (h);
#endif
@@ -216,9 +225,10 @@ void BV (clib_bihash_free) (BVT (clib_bihash) * h)
{
int i;
- if (PREDICT_FALSE (alloc_arena (h) == 0))
+ if (PREDICT_FALSE (h->instantiated == 0))
goto never_initialized;
+ h->instantiated = 0;
vec_free (h->working_copies);
vec_free (h->working_copy_lengths);
#if BIHASH_32_64_SVM == 0
@@ -452,12 +462,19 @@ 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))
+ /*
+ * Create the table (is_add=1,2), or flunk the request now (is_add=0)
+ * Use the alloc_lock to protect the instantiate operation.
+ */
+ if (PREDICT_FALSE (h->instantiated == 0))
{
if (is_add == 0)
return (-1);
- BV (clib_bihash_instantiate) (h);
+
+ BV (clib_bihash_alloc_lock) (h);
+ if (h->instantiated == 0)
+ BV (clib_bihash_instantiate) (h);
+ BV (clib_bihash_alloc_unlock) (h);
}
hash = BV (clib_bihash_hash) (add_v);
diff --git a/src/vppinfra/bihash_template.h b/src/vppinfra/bihash_template.h
index 2e2ba911b7c..0865c2b3ab4 100644
--- a/src/vppinfra/bihash_template.h
+++ b/src/vppinfra/bihash_template.h
@@ -142,6 +142,7 @@ BVS (clib_bihash)
#endif
u64 alloc_arena; /* Base of the allocation arena */
+ volatile u8 instantiated;
/**
* A custom format function to print the Key and Value of bihash_key instead of default hexdump