summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/svm/fifo_segment.c46
-rw-r--r--src/svm/fifo_segment.h2
2 files changed, 44 insertions, 4 deletions
diff --git a/src/svm/fifo_segment.c b/src/svm/fifo_segment.c
index 01fa65623c5..58e392d7246 100644
--- a/src/svm/fifo_segment.c
+++ b/src/svm/fifo_segment.c
@@ -43,7 +43,32 @@ fsh_free_bytes_sub (fifo_segment_header_t * fsh, int size)
static inline uword
fsh_n_free_bytes (fifo_segment_header_t * fsh)
{
- return clib_atomic_load_relax_n (&fsh->n_free_bytes);
+ uword n_free = clib_atomic_load_relax_n (&fsh->n_free_bytes);
+ return n_free > fsh->n_reserved_bytes ? n_free - fsh->n_reserved_bytes : 0;
+}
+
+static inline void
+fsh_update_free_btes (fifo_segment_header_t * fsh)
+{
+ clib_atomic_store_rel_n (&fsh->n_free_bytes,
+ fs_free_space (fsh->ssvm_sh->heap));
+}
+
+static void
+fsh_check_mem (fifo_segment_header_t * fsh)
+{
+ uword thresh;
+
+ if (fsh->flags & FIFO_SEGMENT_F_MEM_LIMIT)
+ return;
+
+ thresh = clib_max (0.01 * fsh->ssvm_sh->ssvm_size,
+ 2 * fsh->n_reserved_bytes);
+ if (fsh->n_free_bytes > thresh)
+ return;
+
+ fsh->flags |= FIFO_SEGMENT_F_MEM_LIMIT;
+ fsh_update_free_btes (fsh);
}
static inline fifo_segment_slice_t *
@@ -67,7 +92,7 @@ fifo_segment_init (fifo_segment_t * fs)
fifo_segment_header_t *fsh;
fifo_segment_slice_t *fss;
ssvm_shared_header_t *sh;
- u32 max_chunk_sz;
+ u32 max_chunk_sz, max_chunks;
uword max_fifo;
void *oldheap;
int i;
@@ -108,6 +133,8 @@ fifo_segment_init (fifo_segment_t * fs)
ssvm_pop_heap (oldheap);
fsh->n_free_bytes = fs_free_space (fs);
+ max_chunks = fsh->n_free_bytes / FIFO_SEGMENT_MIN_FIFO_SIZE;
+ fsh->n_reserved_bytes = (max_chunks / 4) * sizeof (rb_node_t);
sh->ready = 1;
return (0);
}
@@ -393,6 +420,8 @@ fs_try_alloc_fifo (fifo_segment_header_t * fsh, fifo_segment_slice_t * fss,
if (f)
goto done;
}
+
+ fsh_check_mem (fsh);
n_free_bytes = fsh_n_free_bytes (fsh);
if (fifo_sz * FIFO_SEGMENT_ALLOC_BATCH_SIZE < n_free_bytes)
{
@@ -712,6 +741,13 @@ fifo_segment_grow_fifo (fifo_segment_t * fs, svm_fifo_t * f, u32 chunk_size)
if (!c)
{
+ fsh_check_mem (fsh);
+ if (fsh_n_free_bytes (fsh) < chunk_size)
+ {
+ ssvm_pop_heap (oldheap);
+ return -1;
+ }
+
c = svm_fifo_chunk_alloc (chunk_size);
if (!c)
{
@@ -1028,8 +1064,10 @@ format_fifo_segment (u8 * s, va_list * args)
format_white_space, indent + 2, format_memory_size, chunk_bytes,
chunk_bytes, format_memory_size, est_chunk_bytes,
est_chunk_bytes);
- s = format (s, "%Ufifo hdr free bytes: %U (%u)\n", format_white_space,
- indent + 2, format_memory_size, fifo_hdr, fifo_hdr);
+ s = format (s, "%Ufifo hdr free bytes: %U (%u) reserved %U (%lu)\n",
+ format_white_space, indent + 2, format_memory_size, fifo_hdr,
+ fifo_hdr, format_memory_size, fsh->n_reserved_bytes,
+ fsh->n_reserved_bytes);
s = format (s, "\n");
return s;
diff --git a/src/svm/fifo_segment.h b/src/svm/fifo_segment.h
index d363c6058a7..02d45d3244d 100644
--- a/src/svm/fifo_segment.h
+++ b/src/svm/fifo_segment.h
@@ -35,6 +35,7 @@ typedef enum fifo_segment_flags_
{
FIFO_SEGMENT_F_IS_PREALLOCATED = 1 << 0,
FIFO_SEGMENT_F_WILL_DELETE = 1 << 1,
+ FIFO_SEGMENT_F_MEM_LIMIT = 1 << 2,
} fifo_segment_flags_t;
typedef struct fifo_segment_slice_
@@ -51,6 +52,7 @@ typedef struct
ssvm_shared_header_t *ssvm_sh; /**< Pointer to fs ssvm shared hdr */
uword n_free_bytes; /**< Segment free bytes */
u32 n_active_fifos; /**< Number of active fifos */
+ u32 n_reserved_bytes; /**< Bytes not to be allocated */
u32 max_log2_chunk_size; /**< Max log2(chunk size) for fs */
u8 flags; /**< Segment flags */
u8 n_slices; /**< Number of slices */