diff options
-rw-r--r-- | src/svm/fifo_segment.c | 46 | ||||
-rw-r--r-- | src/svm/fifo_segment.h | 2 |
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 */ |