svm: support multi-chunk fifo chunk alloc
Type: feature Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: Id601cd241a2d124d3189057edab4299ffde7ee32
This commit is contained in:

committed by
Dave Barach

parent
9e61d9a1aa
commit
8e755a16a7
@ -2260,10 +2260,11 @@ sfifo_test_fifo_segment_fifo_grow (int verbose)
|
||||
/*
|
||||
* Allocate fifo and try to grow beyond available space
|
||||
*/
|
||||
f = fifo_segment_alloc_fifo (fs, fifo_size, FIFO_SEGMENT_RX_FIFO);
|
||||
f = fifo_segment_alloc_fifo (fs, fifo_segment_free_bytes (fs),
|
||||
FIFO_SEGMENT_RX_FIFO);
|
||||
|
||||
/* Try to force fifo growth */
|
||||
svm_fifo_set_size (f, svm_fifo_size (f) + n_free_chunk_bytes);
|
||||
svm_fifo_set_size (f, svm_fifo_size (f) + n_free_chunk_bytes + 1);
|
||||
validate_test_and_buf_vecs (&test_data, &data_buf, svm_fifo_size (f));
|
||||
rv = svm_fifo_enqueue (f, svm_fifo_size (f), test_data);
|
||||
|
||||
@ -2570,7 +2571,6 @@ sfifo_test_fifo_segment (vlib_main_t * vm, unformat_input_t * input)
|
||||
{
|
||||
int rv, verbose = 0;
|
||||
|
||||
fifo_segment_main_init (&segment_main, HIGH_SEGMENT_BASEVA, 5);
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (input, "verbose"))
|
||||
@ -2632,7 +2632,7 @@ svm_fifo_test (vlib_main_t * vm, unformat_input_t * input,
|
||||
int res = 0;
|
||||
char *str;
|
||||
|
||||
|
||||
fifo_segment_main_init (&segment_main, HIGH_SEGMENT_BASEVA << 3, 5);
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (input, "fifo1"))
|
||||
|
@ -317,6 +317,69 @@ fs_try_alloc_fifo_freelist (fifo_segment_slice_t * fss, u32 fl_index)
|
||||
return f;
|
||||
}
|
||||
|
||||
svm_fifo_chunk_t *
|
||||
fs_try_alloc_multi_chunk (fifo_segment_header_t * fsh,
|
||||
fifo_segment_slice_t * fss, u32 data_bytes)
|
||||
{
|
||||
u32 fl_index, fl_size, n_alloc = 0, req_bytes = data_bytes;
|
||||
svm_fifo_chunk_t *c, *first = 0, *next;
|
||||
|
||||
fl_index = fs_freelist_for_size (req_bytes);
|
||||
if (fl_index > 0)
|
||||
fl_index -= 1;
|
||||
|
||||
fl_size = fs_freelist_index_to_size (fl_index);
|
||||
|
||||
while (req_bytes)
|
||||
{
|
||||
c = fss->free_chunks[fl_index];
|
||||
if (c)
|
||||
{
|
||||
fss->free_chunks[fl_index] = c->next;
|
||||
c->next = first;
|
||||
first = c;
|
||||
n_alloc += fl_size;
|
||||
req_bytes -= clib_min (fl_size, req_bytes);
|
||||
}
|
||||
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);
|
||||
next = c->next;
|
||||
c->next = fss->free_chunks[fl_index];
|
||||
fss->free_chunks[fl_index] = c;
|
||||
fss->n_fl_chunk_bytes += fl_size;
|
||||
c = next;
|
||||
}
|
||||
n_alloc = 0;
|
||||
first = 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
fl_index -= 1;
|
||||
fl_size = fl_size >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
fss->n_fl_chunk_bytes -= n_alloc;
|
||||
fsh_cached_bytes_sub (fsh, n_alloc);
|
||||
return first;
|
||||
}
|
||||
|
||||
static svm_fifo_t *
|
||||
fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_header_t * fsh,
|
||||
fifo_segment_slice_t * fss,
|
||||
@ -403,6 +466,51 @@ fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_header_t * fsh,
|
||||
return f;
|
||||
}
|
||||
|
||||
static int
|
||||
fsh_try_alloc_chunk_batch (fifo_segment_header_t * fsh,
|
||||
fifo_segment_slice_t * fss,
|
||||
u32 fl_index, u32 batch_size)
|
||||
{
|
||||
u32 rounded_data_size;
|
||||
svm_fifo_chunk_t *c;
|
||||
void *oldheap;
|
||||
uword size;
|
||||
u8 *cmem;
|
||||
int i;
|
||||
|
||||
rounded_data_size = fs_freelist_index_to_size (fl_index);
|
||||
size = (uword) (sizeof (*c) + rounded_data_size) * batch_size;
|
||||
|
||||
oldheap = ssvm_push_heap (fsh->ssvm_sh);
|
||||
cmem = clib_mem_alloc_aligned_at_offset (size, CLIB_CACHE_LINE_BYTES,
|
||||
0 /* align_offset */ ,
|
||||
0 /* os_out_of_memory */ );
|
||||
ssvm_pop_heap (oldheap);
|
||||
|
||||
/* Out of space.. */
|
||||
if (cmem == 0)
|
||||
return -1;
|
||||
|
||||
/* Carve fifo + chunk space */
|
||||
for (i = 0; i < batch_size; i++)
|
||||
{
|
||||
c = (svm_fifo_chunk_t *) cmem;
|
||||
c->start_byte = 0;
|
||||
c->length = rounded_data_size;
|
||||
c->enq_rb_index = RBTREE_TNIL_INDEX;
|
||||
c->deq_rb_index = RBTREE_TNIL_INDEX;
|
||||
c->next = fss->free_chunks[fl_index];
|
||||
fss->free_chunks[fl_index] = c;
|
||||
cmem += sizeof (*c) + rounded_data_size;
|
||||
}
|
||||
|
||||
fss->n_fl_chunk_bytes += batch_size * rounded_data_size;
|
||||
fsh_cached_bytes_add (fsh, batch_size * rounded_data_size);
|
||||
fsh_free_bytes_sub (fsh, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fs_try_alloc_fifo_batch (fifo_segment_header_t * fsh,
|
||||
fifo_segment_slice_t * fss,
|
||||
@ -528,18 +636,28 @@ fsh_alloc_chunk (fifo_segment_header_t * fsh, u32 slice_index, u32 chunk_size)
|
||||
svm_fifo_chunk_t *c;
|
||||
void *oldheap;
|
||||
int fl_index;
|
||||
uword n_free;
|
||||
|
||||
fl_index = fs_freelist_for_size (chunk_size);
|
||||
fss = fsh_slice_get (fsh, slice_index);
|
||||
|
||||
clib_spinlock_lock (&fss->chunk_lock);
|
||||
|
||||
c = fss->free_chunks[fl_index];
|
||||
|
||||
if (!c)
|
||||
if (c)
|
||||
{
|
||||
fss->free_chunks[fl_index] = c->next;
|
||||
c->next = 0;
|
||||
fss->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
|
||||
fsh_cached_bytes_sub (fsh, fs_freelist_index_to_size (fl_index));
|
||||
}
|
||||
else if (chunk_size <= (n_free = fsh_n_free_bytes (fsh)))
|
||||
{
|
||||
fsh_check_mem (fsh);
|
||||
|
||||
chunk_size = fs_freelist_index_to_size (fl_index);
|
||||
if (fsh_n_free_bytes (fsh) < chunk_size)
|
||||
if (n_free < chunk_size)
|
||||
goto done;
|
||||
|
||||
oldheap = ssvm_push_heap (fsh->ssvm_sh);
|
||||
@ -551,12 +669,20 @@ fsh_alloc_chunk (fifo_segment_header_t * fsh, u32 slice_index, u32 chunk_size)
|
||||
|
||||
fsh_free_bytes_sub (fsh, chunk_size + sizeof (*c));
|
||||
}
|
||||
else
|
||||
else if (chunk_size <= fss->n_fl_chunk_bytes)
|
||||
{
|
||||
fss->free_chunks[fl_index] = c->next;
|
||||
c->next = 0;
|
||||
fss->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
|
||||
fsh_cached_bytes_sub (fsh, fs_freelist_index_to_size (fl_index));
|
||||
c = fs_try_alloc_multi_chunk (fsh, fss, chunk_size);
|
||||
}
|
||||
else if (chunk_size <= fss->n_fl_chunk_bytes + n_free)
|
||||
{
|
||||
u32 min_size = FIFO_SEGMENT_MIN_FIFO_SIZE;
|
||||
u32 batch;
|
||||
|
||||
fsh_check_mem (fsh);
|
||||
batch = (chunk_size - fss->n_fl_chunk_bytes) / min_size;
|
||||
batch = clib_min (batch + 1, n_free / min_size);
|
||||
if (!fsh_try_alloc_chunk_batch (fsh, fss, 0, batch))
|
||||
c = fs_try_alloc_multi_chunk (fsh, fss, chunk_size);
|
||||
}
|
||||
|
||||
done:
|
||||
|
Reference in New Issue
Block a user