+static inline void *BV (alloc_aligned) (BVT (clib_bihash) * h, uword nbytes)
+{
+ uword rv;
+
+ /* Round to an even number of cache lines */
+ nbytes += CLIB_CACHE_LINE_BYTES - 1;
+ nbytes &= ~(CLIB_CACHE_LINE_BYTES - 1);
+
+ rv = alloc_arena_next (h);
+ alloc_arena_next (h) += nbytes;
+
+ if (alloc_arena_next (h) > alloc_arena_size (h))
+ os_out_of_memory ();
+
+ return (void *) (uword) (rv + alloc_arena (h));
+}
+
+static 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);
+ CLIB_MEMORY_BARRIER ();
+ h->instantiated = 1;
+}
+
+void BV (clib_bihash_init2) (BVT (clib_bihash_init2_args) * a)
+{
+ int i;
+ void *oldheap;
+ BVT (clib_bihash) * h = a->h;
+
+ a->nbuckets = 1 << (max_log2 (a->nbuckets));
+
+ h->name = (u8 *) a->name;
+ h->nbuckets = a->nbuckets;
+ h->log2_nbuckets = max_log2 (a->nbuckets);
+ h->memory_size = a->memory_size;
+ h->instantiated = 0;
+ h->fmt_fn = a->fmt_fn;
+
+ alloc_arena (h) = 0;
+
+ /*
+ * Make sure the requested size is rational. The max table
+ * size without playing the alignment card is 64 Gbytes.
+ * If someone starts complaining that's not enough, we can shift
+ * the offset by CLIB_LOG2_CACHE_LINE_BYTES...
+ */
+ ASSERT (h->memory_size < (1ULL << BIHASH_BUCKET_OFFSET_BITS));
+
+ /* Add this hash table to the list */
+ if (a->dont_add_to_all_bihash_list == 0)
+ {
+ for (i = 0; i < vec_len (clib_all_bihashes); i++)
+ if (clib_all_bihashes[i] == h)
+ goto do_lock;
+ oldheap = clib_all_bihash_set_heap ();
+ vec_add1 (clib_all_bihashes, (void *) h);
+ clib_mem_set_heap (oldheap);
+ }
+
+do_lock:
+ if (h->alloc_lock)
+ clib_mem_free ((void *) h->alloc_lock);
+
+ /*
+ * 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 (a->instantiate_immediately)
+ BV (clib_bihash_instantiate) (h);
+}
+