aboutsummaryrefslogtreecommitdiffstats
path: root/src/svm/fifo_segment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/svm/fifo_segment.c')
-rw-r--r--src/svm/fifo_segment.c130
1 files changed, 122 insertions, 8 deletions
diff --git a/src/svm/fifo_segment.c b/src/svm/fifo_segment.c
index 6bf2634a290..9c332d6f1fa 100644
--- a/src/svm/fifo_segment.c
+++ b/src/svm/fifo_segment.c
@@ -237,7 +237,7 @@ fs_free_list_for_size (u32 size)
}
static inline int
-fs_fifo_size_is_valid (u32 size)
+fs_chunk_size_is_valid (u32 size)
{
/*
* 4K minimum. It's not likely that anything good will happen
@@ -293,7 +293,7 @@ fifo_segment_alloc_fifo (fifo_segment_t * fs, u32 data_bytes,
void *oldheap;
int fl_index;
- if (!fs_fifo_size_is_valid (data_bytes))
+ if (!fs_chunk_size_is_valid (data_bytes))
{
clib_warning ("fifo size out of range %d", data_bytes);
return 0;
@@ -304,7 +304,7 @@ fifo_segment_alloc_fifo (fifo_segment_t * fs, u32 data_bytes,
sh = fs->ssvm.sh;
ssvm_lock_non_recursive (sh, 1);
- fsh = (fifo_segment_header_t *) sh->opaque[0];
+ fsh = fs->h;
vec_validate_init_empty (fsh->free_fifos, fl_index, 0);
f = fsh->free_fifos[fl_index];
@@ -363,7 +363,7 @@ done:
* Free fifo allocated in fifo segment
*/
void
-fifo_segment_free_fifo (fifo_segment_t * s, svm_fifo_t * f)
+fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
{
fifo_segment_header_t *fsh;
ssvm_shared_header_t *sh;
@@ -374,8 +374,8 @@ fifo_segment_free_fifo (fifo_segment_t * s, svm_fifo_t * f)
if (--f->refcnt > 0)
return;
- sh = s->ssvm.sh;
- fsh = (fifo_segment_header_t *) sh->opaque[0];
+ sh = fs->ssvm.sh;
+ fsh = fs->h;
fl_index = f->freelist_index;
ASSERT (fl_index < vec_len (fsh->free_fifos));
@@ -399,6 +399,29 @@ fifo_segment_free_fifo (fifo_segment_t * s, svm_fifo_t * f)
f->prev = 0;
fsh->free_fifos[fl_index] = f;
+ /* If fifo has more chunks, free them */
+ if (f->flags & SVM_FIFO_F_MULTI_CHUNK)
+ {
+ svm_fifo_chunk_t *cur, *next;
+ void *oldheap;
+
+ next = f->start_chunk->next;
+ while (next != f->start_chunk)
+ {
+ cur = next;
+ next = next->next;
+ fl_index = fs_free_list_for_size (cur->length);
+ cur->next = fsh->free_chunks[fl_index];
+ fsh->free_chunks[fl_index] = cur;
+ }
+ oldheap = ssvm_push_heap (sh);
+ svm_fifo_free_chunk_lookup (f);
+ ssvm_pop_heap (oldheap);
+ }
+
+ /* not allocated on segment heap */
+ svm_fifo_free_ooo_data (f);
+
if (CLIB_DEBUG)
{
f->master_session_index = ~0;
@@ -431,13 +454,13 @@ fifo_segment_preallocate_fifo_pairs (fifo_segment_t * fs,
if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0)
return;
- if (!fs_fifo_size_is_valid (rx_fifo_size))
+ if (!fs_chunk_size_is_valid (rx_fifo_size))
{
clib_warning ("rx fifo_size out of range %d", rx_fifo_size);
return;
}
- if (!fs_fifo_size_is_valid (tx_fifo_size))
+ if (!fs_chunk_size_is_valid (tx_fifo_size))
{
clib_warning ("tx fifo_size out of range %d", tx_fifo_size);
return;
@@ -502,6 +525,51 @@ fifo_segment_preallocate_fifo_pairs (fifo_segment_t * fs,
ssvm_pop_heap (oldheap);
}
+int
+fifo_segment_grow_fifo (fifo_segment_t * fs, svm_fifo_t * f, u32 chunk_size)
+{
+ ssvm_shared_header_t *sh;
+ svm_fifo_chunk_t *c;
+ void *oldheap;
+ int fl_index;
+
+ if (!fs_chunk_size_is_valid (chunk_size))
+ {
+ clib_warning ("chunk size out of range %d", chunk_size);
+ return 0;
+ }
+
+ fl_index = fs_free_list_for_size (chunk_size);
+
+ sh = fs->ssvm.sh;
+ ssvm_lock_non_recursive (sh, 1);
+
+ vec_validate_init_empty (fs->h->free_chunks, fl_index, 0);
+ c = fs->h->free_chunks[fl_index];
+
+ oldheap = ssvm_push_heap (sh);
+
+ if (!c)
+ {
+ c = svm_fifo_chunk_alloc (chunk_size);
+ if (!c)
+ {
+ ssvm_pop_heap (oldheap);
+ return -1;
+ }
+ }
+ else
+ {
+ fs->h->free_chunks[fl_index] = c->next;
+ }
+
+ svm_fifo_add_chunk (f, c);
+
+ ssvm_pop_heap (oldheap);
+ ssvm_unlock_non_recursive (sh);
+ return 0;
+}
+
/**
* Get number of active fifos
*/
@@ -559,6 +627,52 @@ fifo_segment_num_free_fifos (fifo_segment_t * fs, u32 fifo_size_in_bytes)
return count;
}
+u32
+fifo_segment_num_free_chunks (fifo_segment_t * fs, u32 size)
+{
+ u32 count = 0, rounded_size, fl_index;
+ fifo_segment_header_t *fsh;
+ svm_fifo_chunk_t *c;
+ int i;
+
+ fsh = fs->h;
+
+ /* Count all free chunks? */
+ if (size == ~0)
+ {
+ for (i = 0; i < vec_len (fsh->free_chunks); i++)
+ {
+ c = fsh->free_chunks[i];
+ if (c == 0)
+ continue;
+
+ while (c)
+ {
+ c = c->next;
+ count++;
+ }
+ }
+ return count;
+ }
+
+ rounded_size = (1 << (max_log2 (size)));
+ fl_index = fs_free_list_for_size (rounded_size);
+
+ if (fl_index >= vec_len (fsh->free_chunks))
+ return 0;
+
+ c = fsh->free_chunks[fl_index];
+ if (c == 0)
+ return 0;
+
+ while (c)
+ {
+ c = c->next;
+ count++;
+ }
+ return count;
+}
+
u8
fifo_segment_has_fifos (fifo_segment_t * fs)
{