summaryrefslogtreecommitdiffstats
path: root/src/vppinfra/vec_bootstrap.h
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2022-03-19 00:07:52 +0100
committerFlorin Coras <florin.coras@gmail.com>2022-03-30 18:27:13 +0000
commit299571aca34d36e637e43cfbba6275662d0d7795 (patch)
treea48be21950d082afb7dd93562f76f0ba554e8919 /src/vppinfra/vec_bootstrap.h
parent9539647b895c456ca53892a9259e3127c6b92d35 (diff)
vppinfra: vector allocator rework
- support of in-place growth of vectors (if there is available space next to existing alloc) - drops the need for alloc_aligned_at_offset from memory allocator, which allows easier swap to different memory allocator and reduces malloc overhead - rework of pool and vec macros to inline functions to improve debuggability - fix alignment - in many cases macros were not using native alignment of the particular datatype. Explicitly setting alignment with XXX_aligned() versions of the macro is not needed anymore in > 99% of cases - fix ASAN usage - avoid use of vector of voids, this was root cause of several bugs found in vec_* and pool_* function where sizeof() was used on voids instead of real vector data type - introduce minimal alignment which is currently 8 bytes, vectors will be always aligned at least to that value (underlay allocator actually always provide 16-byte aligned allocs) Type: improvement Change-Id: I20f4b081bb13bbf7bc0ace85cc4e301787f12fdf Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/vppinfra/vec_bootstrap.h')
-rw-r--r--src/vppinfra/vec_bootstrap.h52
1 files changed, 30 insertions, 22 deletions
diff --git a/src/vppinfra/vec_bootstrap.h b/src/vppinfra/vec_bootstrap.h
index bb6ac84e734..304ea2dee1a 100644
--- a/src/vppinfra/vec_bootstrap.h
+++ b/src/vppinfra/vec_bootstrap.h
@@ -55,13 +55,13 @@
typedef struct
{
u32 len; /**< Number of elements in vector (NOT its allocated length). */
- u8 hdr_size; /**< header size divided by VEC_HEADER_ROUND */
+ u8 hdr_size; /**< header size divided by VEC_MIN_ALIGN */
u8 log2_align; /**< data alignment */
u8 vpad[2]; /**< pad to 8 bytes */
u8 vector_data[0]; /**< Vector data . */
} vec_header_t;
-#define VEC_HEADER_ROUND 8
+#define VEC_MIN_ALIGN 8
/** \brief Find the vector header
@@ -73,19 +73,20 @@ typedef struct
*/
#define _vec_find(v) ((vec_header_t *) (v) - 1)
+always_inline uword __vec_align (uword data_align, uword configuered_align);
+always_inline uword __vec_elt_sz (uword elt_sz, int is_void);
+
#define _vec_round_size(s) \
(((s) + sizeof (uword) - 1) &~ (sizeof (uword) - 1))
+#define _vec_is_void(P) \
+ __builtin_types_compatible_p (__typeof__ ((P)[0]), void)
+#define _vec_elt_sz(V) __vec_elt_sz (sizeof ((V)[0]), _vec_is_void (V))
+#define _vec_align(V, A) __vec_align (__alignof__((V)[0]), A)
-always_inline uword
-vec_header_bytes (uword header_bytes)
-{
- return round_pow2 (header_bytes + sizeof (vec_header_t), VEC_HEADER_ROUND);
-}
-
-always_inline uword
+always_inline CLIB_NOSANITIZE_ADDR uword
vec_get_header_size (void *v)
{
- uword header_size = _vec_find (v)->hdr_size * VEC_HEADER_ROUND;
+ uword header_size = _vec_find (v)->hdr_size * VEC_MIN_ALIGN;
return header_size;
}
@@ -141,11 +142,7 @@ u32 vec_len_not_inline (void *v);
* @return memory size allocated for the vector
*/
-always_inline uword
-vec_mem_size (void *v)
-{
- return v ? clib_mem_size (v - vec_get_header_size (v)) : 0;
-}
+uword vec_mem_size (void *v);
/**
* Number of elements that can fit into generic vector
@@ -156,24 +153,35 @@ vec_mem_size (void *v)
*/
always_inline uword
-_vec_max_len (void *v, uword elt_size)
+vec_max_bytes (void *v)
{
- return v ? vec_mem_size (v) / elt_size : 0;
+ return v ? vec_mem_size (v) - vec_get_header_size (v) : 0;
}
-#define vec_max_len(v) _vec_max_len (v, sizeof ((v)[0]))
+always_inline uword
+_vec_max_len (void *v, uword elt_sz)
+{
+ return vec_max_bytes (v) / elt_sz;
+}
+
+#define vec_max_len(v) _vec_max_len (v, _vec_elt_sz (v))
always_inline void
-_vec_set_len (void *v, uword len, uword elt_size)
+_vec_set_len (void *v, uword len, uword elt_sz)
{
ASSERT (v);
- ASSERT (len <= vec_max_len (v));
+ ASSERT (len <= _vec_max_len (v, elt_sz));
+ uword old_len = _vec_len (v);
+
+ if (len > old_len)
+ CLIB_MEM_UNPOISON (v + old_len * elt_sz, (len - old_len) * elt_sz);
+ else if (len > old_len)
+ CLIB_MEM_POISON (v + len * elt_sz, (old_len - len) * elt_sz);
- CLIB_MEM_POISON_LEN (v, _vec_len (v) * elt_size, len * elt_size);
_vec_len (v) = len;
}
-#define vec_set_len(v, l) _vec_set_len ((void *) v, l, sizeof ((v)[0]))
+#define vec_set_len(v, l) _vec_set_len ((void *) v, l, _vec_elt_sz (v))
/** \brief Reset vector length to zero
NULL-pointer tolerant