X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvppinfra%2Fvec.h;h=1e2f614d9106d094c8010b5f33e7f1fe96a32e3c;hb=3cfd529bd0f7c11ad39ad82a704d95ee5e818013;hp=d4063e64bdcb8cb3c76737bdb793d6914940b4ce;hpb=d25147d58117a573fd2fc04cdfa76339fa1cdf22;p=vpp.git diff --git a/src/vppinfra/vec.h b/src/vppinfra/vec.h index d4063e64bdc..1e2f614d910 100644 --- a/src/vppinfra/vec.h +++ b/src/vppinfra/vec.h @@ -96,14 +96,11 @@ @param data_bytes requested size in bytes @param header_bytes header size in bytes (may be zero) @param data_align alignment (may be zero) - @param numa_id numa id (may be zero) @return v_prime pointer to resized vector, may or may not equal v */ -void *vec_resize_allocate_memory (void *v, - word length_increment, - uword data_bytes, - uword header_bytes, uword data_align, - uword numa_id); +void *vec_resize_allocate_memory (void *v, word length_increment, + uword data_bytes, uword header_bytes, + uword data_align); /** \brief Low-level vector resize function, usually not called directly @@ -112,29 +109,23 @@ void *vec_resize_allocate_memory (void *v, @param data_bytes requested size in bytes @param header_bytes header size in bytes (may be zero) @param data_align alignment (may be zero) - @param numa_id (may be ~0) @return v_prime pointer to resized vector, may or may not equal v */ -#define _vec_resize_numa(V,L,DB,HB,A,S) \ -({ \ - __typeof__ ((V)) _V; \ - _V = _vec_resize_inline((void *)V,L,DB,HB,clib_max((__alignof__((V)[0])),(A)),(S)); \ - _V; \ -}) - -#define _vec_resize(V,L,DB,HB,A) \ - _vec_resize_numa(V,L,DB,HB,A,VEC_NUMA_UNSPECIFIED) +#define _vec_resize(V, L, DB, HB, A) \ + ({ \ + __typeof__ ((V)) _V; \ + _V = _vec_resize_inline ((void *) V, L, DB, HB, \ + clib_max ((__alignof__((V)[0])), (A))); \ + _V; \ + }) always_inline void * -_vec_resize_inline (void *v, - word length_increment, - uword data_bytes, uword header_bytes, uword data_align, - uword numa_id) +_vec_resize_inline (void *v, word length_increment, uword data_bytes, + uword header_bytes, uword data_align) { vec_header_t *vh = _vec_find (v); uword new_data_bytes, aligned_header_bytes; - void *oldheap; aligned_header_bytes = vec_header_bytes (header_bytes); @@ -144,12 +135,6 @@ _vec_resize_inline (void *v, { void *p = v - aligned_header_bytes; - if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED)) - { - oldheap = clib_mem_get_per_cpu_heap (); - clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap (numa_id)); - } - /* Vector header must start heap object. */ ASSERT (clib_mem_is_heap_object (p)); @@ -158,19 +143,14 @@ _vec_resize_inline (void *v, { CLIB_MEM_UNPOISON (v, data_bytes); vh->len += length_increment; - if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED)) - clib_mem_set_per_cpu_heap (oldheap); return v; } - if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED)) - clib_mem_set_per_cpu_heap (oldheap); } /* Slow path: call helper function. */ - return vec_resize_allocate_memory (v, length_increment, data_bytes, - header_bytes, - clib_max (sizeof (vec_header_t), - data_align), numa_id); + return vec_resize_allocate_memory ( + v, length_increment, data_bytes, header_bytes, + clib_max (sizeof (vec_header_t), data_align)); } /** \brief Determine if vector will resize with next allocation @@ -184,40 +164,28 @@ _vec_resize_inline (void *v, */ always_inline int -_vec_resize_will_expand (void *v, - word length_increment, - uword data_bytes, uword header_bytes, - uword data_align) +_vec_resize_will_expand (void *v, uword n_elts, uword elt_size) { - uword new_data_bytes, aligned_header_bytes; - - aligned_header_bytes = vec_header_bytes (header_bytes); - - new_data_bytes = data_bytes + aligned_header_bytes; - if (PREDICT_TRUE (v != 0)) { - void *p = v - aligned_header_bytes; - /* Vector header must start heap object. */ - ASSERT (clib_mem_is_heap_object (p)); + ASSERT (clib_mem_is_heap_object (vec_header (v))); - /* Typically we'll not need to resize. */ - if (new_data_bytes <= clib_mem_size (p)) + if (vec_mem_size (v) >= ((_vec_len (v) + n_elts)) * elt_size) return 0; } return 1; } -/** \brief Predicate function, says whether the supplied vector is a clib heap - object (general version). +/** \brief Determine if vector will resize with next allocation - @param v pointer to a vector - @param header_bytes vector header size in bytes (may be zero) - @return 0 or 1 + @param V pointer to a vector + @param N number of elements to add + @return 1 if vector will resize 0 otherwise */ -uword clib_mem_is_vec_h (void *v, uword header_bytes); +#define vec_resize_will_expand(V, N) \ + _vec_resize_will_expand (V, N, sizeof ((V)[0])) /** \brief Predicate function, says whether the supplied vector is a clib heap object @@ -228,7 +196,7 @@ uword clib_mem_is_vec_h (void *v, uword header_bytes); always_inline uword clib_mem_is_vec (void *v) { - return clib_mem_is_vec_h (v, 0); + return clib_mem_is_heap_object (vec_header (v)); } /* Local variable naming macro (prevents collisions with other macro naming). */ @@ -243,31 +211,18 @@ clib_mem_is_vec (void *v) @param N number of elements to add @param H header size in bytes (may be zero) @param A alignment (may be zero) - @param S numa_id (may be zero) @return V (value-result macro parameter) */ -#define vec_resize_has(V,N,H,A,S) \ -do { \ - word _v(n) = (N); \ - word _v(l) = vec_len (V); \ - V = _vec_resize_numa ((V), _v(n), \ - (_v(l) + _v(n)) * sizeof ((V)[0]), \ - (H), (A),(S)); \ -} while (0) - -/** \brief Resize a vector (less general version). - Add N elements to end of given vector V, return pointer to start of vector. - Vector will have room for H header bytes and will have user's data aligned - at alignment A (rounded to next power of 2). - - @param V pointer to a vector - @param N number of elements to add - @param H header size in bytes (may be zero) - @param A alignment (may be zero) - @return V (value-result macro parameter) -*/ -#define vec_resize_ha(V,N,H,A) vec_resize_has(V,N,H,A,VEC_NUMA_UNSPECIFIED) +#define vec_resize_ha(V, N, H, A) \ + do \ + { \ + word _v (n) = (N); \ + word _v (l) = vec_len (V); \ + V = _vec_resize ((V), _v (n), (_v (l) + _v (n)) * sizeof ((V)[0]), (H), \ + (A)); \ + } \ + while (0) /** \brief Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V, return pointer to start of vector. @@ -358,26 +313,22 @@ do { \ */ #define vec_new_aligned(T,N,A) vec_new_ha(T,N,0,A) -/** \brief Free vector's memory (general version) - - @param V pointer to a vector - @param H size of header in bytes - @return V (value-result parameter, V=0) -*/ -#define vec_free_h(V,H) \ -do { \ - if (V) \ - { \ - clib_mem_free (vec_header ((V), (H))); \ - V = 0; \ - } \ -} while (0) - /** \brief Free vector's memory (no header). @param V pointer to a vector @return V (value-result parameter, V=0) */ -#define vec_free(V) vec_free_h(V,0) +#define vec_free(V) \ + do \ + { \ + if (V) \ + { \ + clib_mem_free (vec_header ((V))); \ + V = 0; \ + } \ + } \ + while (0) + +void vec_free_not_inline (void *v); /**\brief Free vector user header (syntactic sugar) @param h vector header @@ -390,34 +341,21 @@ do { \ @param V pointer to a vector @param H size of header in bytes @param A alignment (may be zero) - @param S numa (may be VEC_NUMA_UNSPECIFIED) @return Vdup copy of vector */ -#define vec_dup_ha_numa(V,H,A,S) \ -({ \ - __typeof__ ((V)[0]) * _v(v) = 0; \ - uword _v(l) = vec_len (V); \ - if (_v(l) > 0) \ - { \ - vec_resize_has (_v(v), _v(l), (H), (A), (S)); \ - clib_memcpy_fast (_v(v), (V), _v(l) * sizeof ((V)[0]));\ - } \ - _v(v); \ -}) - -/** \brief Return copy of vector (VEC_NUMA_UNSPECIFIED). - - @param V pointer to a vector - @param H size of header in bytes - @param A alignment (may be zero) - - @return Vdup copy of vector -*/ -#define vec_dup_ha(V,H,A) \ - vec_dup_ha_numa(V,H,A,VEC_NUMA_UNSPECIFIED) - +#define vec_dup_ha(V, H, A) \ + ({ \ + __typeof__ ((V)[0]) *_v (v) = 0; \ + uword _v (l) = vec_len (V); \ + if (_v (l) > 0) \ + { \ + vec_resize_ha (_v (v), _v (l), (H), (A)); \ + clib_memcpy_fast (_v (v), (V), _v (l) * sizeof ((V)[0])); \ + } \ + _v (v); \ + }) /** \brief Return copy of vector (no header, no alignment) @@ -463,39 +401,27 @@ do { \ @param I vector index which will be valid upon return @param H header size in bytes (may be zero) @param A alignment (may be zero) - @param N numa_id (may be zero) @return V (value-result macro parameter) */ -#define vec_validate_han(V,I,H,A,N) \ -do { \ - void *oldheap; \ - STATIC_ASSERT(A==0 || ((A % sizeof(V[0]))==0) \ - || ((sizeof(V[0]) % A) == 0), \ - "vector validate aligned on incorrectly sized object"); \ - word _v(i) = (I); \ - word _v(l) = vec_len (V); \ - if (_v(i) >= _v(l)) \ - { \ - /* switch to the per-numa heap if directed */ \ - if (PREDICT_FALSE(N != VEC_NUMA_UNSPECIFIED)) \ - { \ - oldheap = clib_mem_get_per_cpu_heap(); \ - clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap(N)); \ - } \ - \ - vec_resize_ha ((V), 1 + (_v(i) - _v(l)), (H), (A)); \ - /* Must zero new space since user may have previously \ - used e.g. _vec_len (v) -= 10 */ \ - clib_memset ((V) + _v(l), 0, \ - (1 + (_v(i) - _v(l))) * sizeof ((V)[0])); \ - /* Switch back to the global heap */ \ - if (PREDICT_FALSE (N != VEC_NUMA_UNSPECIFIED)) \ - clib_mem_set_per_cpu_heap (oldheap); \ - } \ -} while (0) - -#define vec_validate_ha(V,I,H,A) vec_validate_han(V,I,H,A,VEC_NUMA_UNSPECIFIED) +#define vec_validate_ha(V, I, H, A) \ + do \ + { \ + STATIC_ASSERT (A == 0 || ((A % sizeof (V[0])) == 0) || \ + ((sizeof (V[0]) % A) == 0), \ + "vector validate aligned on incorrectly sized object"); \ + word _v (i) = (I); \ + word _v (l) = vec_len (V); \ + if (_v (i) >= _v (l)) \ + { \ + vec_resize_ha ((V), 1 + (_v (i) - _v (l)), (H), (A)); \ + /* Must zero new space since user may have previously \ + used e.g. _vec_len (v) -= 10 */ \ + clib_memset ((V) + _v (l), 0, \ + (1 + (_v (i) - _v (l))) * sizeof ((V)[0])); \ + } \ + } \ + while (0) /** \brief Make sure vector is long enough for given index (no header, unspecified alignment) @@ -648,13 +574,19 @@ do { \ @param A alignment (may be zero) @return V (value-result macro parameter) */ -#define vec_add_ha(V,E,N,H,A) \ -do { \ - word _v(n) = (N); \ - word _v(l) = vec_len (V); \ - V = _vec_resize ((V), _v(n), (_v(l) + _v(n)) * sizeof ((V)[0]), (H), (A)); \ - clib_memcpy_fast ((V) + _v(l), (E), _v(n) * sizeof ((V)[0])); \ -} while (0) +#define vec_add_ha(V, E, N, H, A) \ + do \ + { \ + word _v (n) = (N); \ + if (PREDICT_TRUE (_v (n) > 0)) \ + { \ + word _v (l) = vec_len (V); \ + V = _vec_resize ((V), _v (n), (_v (l) + _v (n)) * sizeof ((V)[0]), \ + (H), (A)); \ + clib_memcpy_fast ((V) + _v (l), (E), _v (n) * sizeof ((V)[0])); \ + } \ + } \ + while (0) /** \brief Add N elements to end of vector V (no header, unspecified alignment) @@ -802,22 +734,23 @@ do { \ @return V (value-result macro parameter) */ -#define vec_insert_elts_ha(V,E,N,M,H,A) \ -do { \ - word _v(l) = vec_len (V); \ - word _v(n) = (N); \ - word _v(m) = (M); \ - V = _vec_resize ((V), \ - _v(n), \ - (_v(l) + _v(n))*sizeof((V)[0]), \ - (H), (A)); \ - ASSERT (_v(m) <= _v(l)); \ - memmove ((V) + _v(m) + _v(n), \ - (V) + _v(m), \ - (_v(l) - _v(m)) * sizeof ((V)[0])); \ - clib_memcpy_fast ((V) + _v(m), (E), \ - _v(n) * sizeof ((V)[0])); \ -} while (0) +#define vec_insert_elts_ha(V, E, N, M, H, A) \ + do \ + { \ + word _v (n) = (N); \ + if (PREDICT_TRUE (_v (n) > 0)) \ + { \ + word _v (l) = vec_len (V); \ + word _v (m) = (M); \ + V = _vec_resize ((V), _v (n), (_v (l) + _v (n)) * sizeof ((V)[0]), \ + (H), (A)); \ + ASSERT (_v (m) <= _v (l)); \ + memmove ((V) + _v (m) + _v (n), (V) + _v (m), \ + (_v (l) - _v (m)) * sizeof ((V)[0])); \ + clib_memcpy_fast ((V) + _v (m), (E), _v (n) * sizeof ((V)[0])); \ + } \ + } \ + while (0) /** \brief Insert N vector elements starting at element M, insert given elements (no header, unspecified alignment) @@ -885,15 +818,21 @@ do { \ @param V2 vector to append */ -#define vec_append(v1,v2) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \ - clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) +#define vec_append(v1, v2) \ + do \ + { \ + uword _v (l1) = vec_len (v1); \ + uword _v (l2) = vec_len (v2); \ + \ + if (PREDICT_TRUE (_v (l2) > 0)) \ + { \ + v1 = _vec_resize ((v1), _v (l2), \ + (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, 0); \ + clib_memcpy_fast ((v1) + _v (l1), (v2), \ + _v (l2) * sizeof ((v2)[0])); \ + } \ + } \ + while (0) /** \brief Append v2 after v1. Result in v1. Specified alignment. @param V1 target vector @@ -901,31 +840,42 @@ do { \ @param align required alignment */ -#define vec_append_aligned(v1,v2,align) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \ - clib_memcpy_fast ((v1) + _v(l1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) +#define vec_append_aligned(v1, v2, align) \ + do \ + { \ + uword _v (l1) = vec_len (v1); \ + uword _v (l2) = vec_len (v2); \ + \ + if (PREDICT_TRUE (_v (l2) > 0)) \ + { \ + v1 = _vec_resize ( \ + (v1), _v (l2), (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, align); \ + clib_memcpy_fast ((v1) + _v (l1), (v2), \ + _v (l2) * sizeof ((v2)[0])); \ + } \ + } \ + while (0) /** \brief Prepend v2 before v1. Result in v1. @param V1 target vector @param V2 vector to prepend */ -#define vec_prepend(v1,v2) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, 0); \ - memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \ - clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) +#define vec_prepend(v1, v2) \ + do \ + { \ + uword _v (l1) = vec_len (v1); \ + uword _v (l2) = vec_len (v2); \ + \ + if (PREDICT_TRUE (_v (l2) > 0)) \ + { \ + v1 = _vec_resize ((v1), _v (l2), \ + (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, 0); \ + memmove ((v1) + _v (l2), (v1), _v (l1) * sizeof ((v1)[0])); \ + clib_memcpy_fast ((v1), (v2), _v (l2) * sizeof ((v2)[0])); \ + } \ + } \ + while (0) /** \brief Prepend v2 before v1. Result in v1. Specified alignment @param V1 target vector @@ -933,17 +883,21 @@ do { \ @param align required alignment */ -#define vec_prepend_aligned(v1,v2,align) \ -do { \ - uword _v(l1) = vec_len (v1); \ - uword _v(l2) = vec_len (v2); \ - \ - v1 = _vec_resize ((v1), _v(l2), \ - (_v(l1) + _v(l2)) * sizeof ((v1)[0]), 0, align); \ - memmove ((v1) + _v(l2), (v1), _v(l1) * sizeof ((v1)[0])); \ - clib_memcpy_fast ((v1), (v2), _v(l2) * sizeof ((v2)[0])); \ -} while (0) - +#define vec_prepend_aligned(v1, v2, align) \ + do \ + { \ + uword _v (l1) = vec_len (v1); \ + uword _v (l2) = vec_len (v2); \ + \ + if (PREDICT_TRUE (_v (l2) > 0)) \ + { \ + v1 = _vec_resize ( \ + (v1), _v (l2), (_v (l1) + _v (l2)) * sizeof ((v1)[0]), 0, align); \ + memmove ((v1) + _v (l2), (v1), _v (l1) * sizeof ((v1)[0])); \ + clib_memcpy_fast ((v1), (v2), _v (l2) * sizeof ((v2)[0])); \ + } \ + } \ + while (0) /** \brief Zero all vector elements. Null-pointer tolerant. @param var Vector to zero