vppinfra: fix corner cases in tw_timer_expire
[vpp.git] / src / svm / fifo_segment.c
index ec6f082..816f711 100644 (file)
@@ -75,7 +75,6 @@ static inline uword
 fsh_n_cached_bytes (fifo_segment_header_t * fsh)
 {
   uword n_cached = clib_atomic_load_relax_n (&fsh->n_cached_bytes);
-  ASSERT (n_cached >= 0);
   return n_cached;
 }
 
@@ -117,7 +116,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, max_chunks;
+  u32 max_chunk_sz;
   uword max_fifo;
   void *oldheap;
   int i;
@@ -160,8 +159,7 @@ fifo_segment_init (fifo_segment_t * fs)
 
   fsh->n_free_bytes = fsh_free_space (fsh);
   fsh->n_cached_bytes = 0;
-  max_chunks = fsh->n_free_bytes / FIFO_SEGMENT_MIN_FIFO_SIZE;
-  fsh->n_reserved_bytes = (max_chunks / 4) * sizeof (rb_node_t);
+  fsh->n_reserved_bytes = clib_min (0.01 * fsh->n_free_bytes, 256 << 10);
   sh->ready = 1;
   return (0);
 }
@@ -385,7 +383,7 @@ 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;
+  svm_fifo_chunk_t *c, *first = 0, *last = 0, *next;
   u32 fl_index, fl_size, n_alloc = 0;
   svm_fifo_t *f;
 
@@ -422,7 +420,7 @@ fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_header_t * fsh,
          c->next = first;
          first = c;
          n_alloc += fl_size;
-         data_bytes -= c->length;
+         data_bytes -= clib_min (fl_size, data_bytes);
        }
       else
        {
@@ -435,11 +433,13 @@ fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_header_t * fsh,
                {
                  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;
                  n_alloc -= fl_size;
                  data_bytes += fl_size;
+                 c = next;
                }
              first = last = 0;
              fl_index = fs_freelist_for_size (data_bytes);
@@ -585,6 +585,8 @@ fs_try_alloc_fifo (fifo_segment_header_t * fsh, fifo_segment_slice_t * fss,
   fifo_sz = sizeof (svm_fifo_t) + sizeof (svm_fifo_chunk_t);
   fifo_sz += 1 << max_log2 (min_size);
 
+  clib_spinlock_lock (&fss->chunk_lock);
+
   if (fss->free_fifos && fss->free_chunks[fl_index])
     {
       f = fs_try_alloc_fifo_freelist (fss, fl_index);
@@ -619,13 +621,19 @@ fs_try_alloc_fifo (fifo_segment_header_t * fsh, fifo_segment_slice_t * fss,
          goto done;
        }
     }
-  if (data_bytes <= fss->n_fl_chunk_bytes)
-    f = fs_try_alloc_fifo_freelist_multi_chunk (fsh, fss, data_bytes);
+  /* All failed, try to allocate min of data bytes and fifo sz */
+  fifo_sz = clib_min (fifo_sz, data_bytes);
+  if (fifo_sz <= fss->n_fl_chunk_bytes)
+    f = fs_try_alloc_fifo_freelist_multi_chunk (fsh, fss, fifo_sz);
 
 done:
+  clib_spinlock_unlock (&fss->chunk_lock);
 
   if (f)
-    f->fs_hdr = fsh;
+    {
+      f->size = data_bytes;
+      f->fs_hdr = fsh;
+    }
   return f;
 }
 
@@ -1124,6 +1132,12 @@ fifo_segment_cached_bytes (fifo_segment_t * fs)
   return fsh_n_cached_bytes (fs->h);
 }
 
+uword
+fifo_segment_available_bytes (fifo_segment_t * fs)
+{
+  return fsh_n_free_bytes (fs->h) + fsh_n_cached_bytes (fs->h);
+}
+
 uword
 fifo_segment_fl_chunk_bytes (fifo_segment_t * fs)
 {