+fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_header_t * fsh,
+ fifo_segment_slice_t * fss,
+ u32 data_bytes)
+{
+ svm_fifo_chunk_t *c, *first = 0, *last = 0;
+ u32 fl_index, fl_size, n_alloc = 0;
+ svm_fifo_t *f;
+
+ f = fss->free_fifos;
+ if (!f)
+ {
+ void *oldheap = ssvm_push_heap (fsh->ssvm_sh);
+ f = clib_mem_alloc_aligned (sizeof (*f), CLIB_CACHE_LINE_BYTES);
+ ssvm_pop_heap (oldheap);
+ if (!f)
+ return 0;
+ memset (f, 0, sizeof (*f));
+ fsh_free_bytes_sub (fsh, sizeof (*f));
+ }
+ else
+ {
+ fss->free_fifos = f->next;
+ }
+
+ fl_index = fs_freelist_for_size (data_bytes);
+ if (fl_index > 0)
+ fl_index -= 1;
+
+ fl_size = fs_freelist_index_to_size (fl_index);
+
+ while (data_bytes)
+ {
+ c = fss->free_chunks[fl_index];
+ if (c)
+ {
+ fss->free_chunks[fl_index] = c->next;
+ if (!last)
+ last = c;
+ c->next = first;
+ first = c;
+ n_alloc += fl_size;
+ data_bytes -= c->length;
+ }
+ else
+ {
+ /* Failed to allocate with smaller chunks */
+ if (fl_index == 0)
+ {
+ /* free all chunks if any allocated */
+ c = first;
+ while (c)
+ {
+ fl_index = fs_freelist_for_size (c->length);
+ fl_size = fs_freelist_index_to_size (fl_index);
+ c->next = fss->free_chunks[fl_index];
+ fss->free_chunks[fl_index] = c;
+ fss->n_fl_chunk_bytes += fl_size;
+ data_bytes += fl_size;
+ }
+ first = last = 0;
+ fl_index = fs_freelist_for_size (data_bytes);
+ if (fss->free_chunks[fl_index + 1])
+ {
+ fl_index += 1;
+ fl_size = fs_freelist_index_to_size (fl_index);
+ continue;
+ }
+
+ f->next = fss->free_fifos;
+ fss->free_fifos = f;
+ return 0;
+ }
+ fl_index -= 1;
+ fl_size = fl_size >> 1;
+ }
+ }
+
+ f->start_chunk = first;
+ f->end_chunk = last;
+ fss->n_fl_chunk_bytes -= n_alloc;
+ return f;
+}
+
+static int
+fs_try_alloc_fifo_batch (fifo_segment_header_t * fsh,
+ fifo_segment_slice_t * fss,
+ u32 fl_index, u32 batch_size)