+ nbytes = round_pow2 (nbytes, CLIB_CACHE_LINE_BYTES);
+
+ if (BIHASH_USE_HEAP)
+ {
+ void *rv, *oldheap;
+ uword page_sz = sizeof (BVT (clib_bihash_value));
+ uword chunk_sz = round_pow2 (page_sz << BIIHASH_MIN_ALLOC_LOG2_PAGES,
+ CLIB_CACHE_LINE_BYTES);
+
+ BVT (clib_bihash_alloc_chunk) * chunk = h->chunks;
+
+ /* if there is enough space in the currenrt chunk */
+ if (chunk && chunk->bytes_left >= nbytes)
+ {
+ rv = chunk->next_alloc;
+ chunk->bytes_left -= nbytes;
+ chunk->next_alloc += nbytes;
+ return rv;
+ }
+
+ /* requested allocation is bigger than chunk size */
+ if (nbytes >= chunk_sz)
+ {
+ oldheap = clib_mem_set_heap (h->heap);
+ chunk = clib_mem_alloc_aligned (nbytes + sizeof (*chunk),
+ CLIB_CACHE_LINE_BYTES);
+ clib_mem_set_heap (oldheap);
+ clib_memset_u8 (chunk, 0, sizeof (*chunk));
+ chunk->size = nbytes;
+ rv = (u8 *) (chunk + 1);
+ if (h->chunks)
+ {
+ /* take 2nd place in the list */
+ chunk->next = h->chunks->next;
+ chunk->prev = h->chunks;
+ h->chunks->next = chunk;
+ if (chunk->next)
+ chunk->next->prev = chunk;
+ }
+ else
+ h->chunks = chunk;
+
+ return rv;
+ }
+
+ oldheap = clib_mem_set_heap (h->heap);
+ chunk = clib_mem_alloc_aligned (chunk_sz + sizeof (*chunk),
+ CLIB_CACHE_LINE_BYTES);
+ clib_mem_set_heap (oldheap);
+ chunk->size = chunk_sz;
+ chunk->bytes_left = chunk_sz;
+ chunk->next_alloc = (u8 *) (chunk + 1);
+ chunk->next = h->chunks;
+ chunk->prev = 0;
+ if (chunk->next)
+ chunk->next->prev = chunk;
+ h->chunks = chunk;
+ rv = chunk->next_alloc;
+ chunk->bytes_left -= nbytes;
+ chunk->next_alloc += nbytes;
+ return rv;
+ }