vppinfra: make first bihash add thread-safe 05/21005/5
authorDave Barach <dave@barachs.net>
Thu, 1 Aug 2019 12:15:01 +0000 (08:15 -0400)
committerFlorin Coras <florin.coras@gmail.com>
Thu, 1 Aug 2019 16:04:06 +0000 (16:04 +0000)
Type: fix

Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: Ie37ff66faba79e3b8f46c7a704137f9ef2acc773

src/vppinfra/bihash_template.c
src/vppinfra/bihash_template.h

index 11e3ac4..4ef32ef 100644 (file)
@@ -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);
index 2e2ba91..0865c2b 100644 (file)
@@ -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