diff options
author | Damjan Marion <damarion@cisco.com> | 2022-03-19 00:07:52 +0100 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2022-03-30 18:27:13 +0000 |
commit | 299571aca34d36e637e43cfbba6275662d0d7795 (patch) | |
tree | a48be21950d082afb7dd93562f76f0ba554e8919 /src/vppinfra/vec_bootstrap.h | |
parent | 9539647b895c456ca53892a9259e3127c6b92d35 (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.h | 52 |
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 |