vppinfra: store vector header size and alignment into header 91/35691/4
authorDamjan Marion <damarion@cisco.com>
Wed, 16 Mar 2022 16:57:29 +0000 (17:57 +0100)
committerFlorin Coras <florin.coras@gmail.com>
Thu, 17 Mar 2022 20:31:14 +0000 (20:31 +0000)
On the forst vector alloc values are stored into header.
Later, when vector grows values from header are used istead of provided
ones.

In the debug image code will assert if same values are not provided.

Type: improvement
Change-Id: I8fdcfa495e9c1df0f6392c90f634e8c74b73b328
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/vppinfra/fifo.c
src/vppinfra/vec.c
src/vppinfra/vec_bootstrap.h

index 52d65ae..1ef1754 100644 (file)
@@ -79,8 +79,9 @@
 __clib_export void *
 _clib_fifo_resize (void *v_old, uword n_new_elts, uword elt_bytes)
 {
-  void *v_new, *end, *head;
-  uword n_old_elts, header_bytes;
+  void *end, *head;
+  u8 *v_new = 0;
+  uword n_old_elts;
   uword n_copy_bytes, n_zero_bytes;
   clib_fifo_header_t *f_new, *f_old;
 
@@ -91,15 +92,12 @@ _clib_fifo_resize (void *v_old, uword n_new_elts, uword elt_bytes)
   else
     n_new_elts = max_pow2 (n_new_elts);
 
-  header_bytes = vec_header_bytes (sizeof (clib_fifo_header_t));
-
-  v_new = clib_mem_alloc_no_fail (n_new_elts * elt_bytes + header_bytes);
-  v_new += header_bytes;
+  vec_alloc_ha (v_new, n_new_elts * elt_bytes, sizeof (clib_fifo_header_t), 0);
+  _vec_len (v_new) = n_new_elts;
 
   f_new = clib_fifo_header (v_new);
   f_new->head_index = 0;
   f_new->tail_index = n_old_elts;
-  _vec_len (v_new) = n_new_elts;
 
   /* Copy old -> new. */
   n_copy_bytes = n_old_elts * elt_bytes;
index 970f7f7..97e2762 100644 (file)
@@ -57,6 +57,7 @@ vec_resize_allocate_memory (void *v,
   void *oldheap;
 
   header_bytes = vec_header_bytes (header_bytes);
+  data_align = data_align == 0 ? 1 : data_align;
 
   data_bytes += header_bytes;
 
@@ -66,6 +67,9 @@ vec_resize_allocate_memory (void *v,
       clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap (numa_id));
     }
 
+  /* alignment must be power of 2 */
+  ASSERT (count_set_bits (data_align) == 1);
+
   if (!v)
     {
       new = clib_mem_alloc_aligned_at_offset (data_bytes, data_align, header_bytes, 1  /* yes, call os_out_of_memory */
@@ -77,11 +81,20 @@ vec_resize_allocate_memory (void *v,
       v = new + header_bytes;
       _vec_len (v) = length_increment;
       _vec_numa (v) = numa_id;
+      ASSERT (header_bytes / VEC_HEADER_ROUND <= 255);
+      _vec_find (v)->hdr_size = header_bytes / VEC_HEADER_ROUND;
+      _vec_find (v)->log2_align = min_log2 (data_align);
       if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
        clib_mem_set_per_cpu_heap (oldheap);
       return v;
     }
 
+  ASSERT (_vec_find (v)->hdr_size * VEC_HEADER_ROUND == header_bytes);
+  header_bytes = _vec_find (v)->hdr_size * VEC_HEADER_ROUND;
+
+  ASSERT (data_align == (1 << _vec_find (v)->log2_align));
+  data_align = 1 << _vec_find (v)->log2_align;
+
   vh->len += length_increment;
   old = v - header_bytes;
 
index f294028..d628d38 100644 (file)
@@ -56,12 +56,16 @@ typedef struct
 {
   u32 len; /**< Number of elements in vector (NOT its allocated length). */
   u8 numa_id; /**< NUMA id */
-  u8 vpad[3]; /**< pad to 8 bytes */
+  u8 hdr_size;       /**< header size divided by VEC_HEADER_ROUND */
+  u8 log2_align;      /**< data alignment */
+  u8 vpad[1];        /**< pad to 8 bytes */
   u8 vector_data[0];  /**< Vector data . */
 } vec_header_t;
 
 #define VEC_NUMA_UNSPECIFIED (0xFF)
 
+#define VEC_HEADER_ROUND 8
+
 /** \brief Find the vector header
 
     Given the user's pointer to a vector, find the corresponding
@@ -78,8 +82,7 @@ typedef struct
 always_inline uword
 vec_header_bytes (uword header_bytes)
 {
-  return round_pow2 (header_bytes + sizeof (vec_header_t),
-                    sizeof (vec_header_t));
+  return round_pow2 (header_bytes + sizeof (vec_header_t), VEC_HEADER_ROUND);
 }
 
 /** \brief Find a user vector header