Line data Source code
1 : /* SPDX-License-Identifier: Apache-2.0
2 : * Copyright(c) 2022 Cisco Systems, Inc.
3 : */
4 :
5 : #include <vppinfra/vec.h>
6 : #include <vppinfra/mem.h>
7 :
8 : #ifndef CLIB_VECTOR_GROW_BY_ONE
9 : #define CLIB_VECTOR_GROW_BY_ONE 0
10 : #endif
11 :
12 : __clib_export uword
13 1285860000 : vec_mem_size (void *v)
14 : {
15 1285860000 : return v ? clib_mem_size (v - vec_get_header_size (v)) : 0;
16 : }
17 :
18 : __clib_export void *
19 49023600 : _vec_alloc_internal (uword n_elts, const vec_attr_t *const attr)
20 : {
21 : uword req_size, alloc_size, data_offset, align;
22 49023600 : uword elt_sz = attr->elt_sz;
23 49023600 : void *p, *v, *heap = attr->heap;
24 :
25 : /* alignment must be power of 2 */
26 49023600 : align = clib_max (attr->align, VEC_MIN_ALIGN);
27 49023600 : ASSERT (count_set_bits (align) == 1);
28 :
29 : /* calc offset where vector data starts */
30 49023600 : data_offset = attr->hdr_sz + sizeof (vec_header_t);
31 49023600 : data_offset += heap ? sizeof (void *) : 0;
32 49023600 : data_offset = round_pow2 (data_offset, align);
33 :
34 49023600 : req_size = data_offset + n_elts * elt_sz;
35 49023600 : p = clib_mem_heap_alloc_aligned (heap, req_size, align);
36 :
37 : /* zero out whole alocation */
38 49024800 : alloc_size = clib_mem_size (p);
39 49024700 : clib_mem_unpoison (p, alloc_size);
40 49024500 : clib_memset_u8 (p, 0, alloc_size);
41 :
42 : /* fill vector header */
43 49024200 : v = p + data_offset;
44 49024200 : _vec_find (v)->len = n_elts;
45 49024200 : _vec_find (v)->hdr_size = data_offset / VEC_MIN_ALIGN;
46 49024200 : _vec_find (v)->log2_align = min_log2 (align);
47 49024300 : if (heap)
48 : {
49 5748 : _vec_find (v)->default_heap = 0;
50 5748 : _vec_heap (v) = heap;
51 : }
52 : else
53 49018500 : _vec_find (v)->default_heap = 1;
54 :
55 : /* poison extra space given by allocator */
56 49024300 : clib_mem_poison (p + req_size, alloc_size - req_size);
57 49024200 : _vec_set_grow_elts (v, (alloc_size - req_size) / elt_sz);
58 49024200 : return v;
59 : }
60 :
61 : static inline void
62 82259400 : _vec_update_len (void *v, uword n_elts, uword elt_sz, uword n_data_bytes,
63 : uword unused_bytes)
64 : {
65 82259400 : _vec_find (v)->len = n_elts;
66 82259400 : _vec_set_grow_elts (v, unused_bytes / elt_sz);
67 82259200 : clib_mem_unpoison (v, n_data_bytes);
68 82259000 : clib_mem_poison (v + n_data_bytes, unused_bytes);
69 82258900 : }
70 :
71 : __clib_export void *
72 25326300 : _vec_realloc_internal (void *v, uword n_elts, const vec_attr_t *const attr)
73 : {
74 : uword old_alloc_sz, new_alloc_sz, new_data_size, n_data_bytes, data_offset;
75 : uword elt_sz;
76 :
77 25326300 : if (PREDICT_FALSE (v == 0))
78 927766 : return _vec_alloc_internal (n_elts, attr);
79 :
80 24398500 : elt_sz = attr->elt_sz;
81 24398500 : n_data_bytes = n_elts * elt_sz;
82 24398500 : data_offset = vec_get_header_size (v);
83 24398300 : new_data_size = data_offset + n_data_bytes;
84 24398300 : new_alloc_sz = old_alloc_sz = clib_mem_size (vec_header (v));
85 :
86 : /* realloc if new size cannot fit into existing allocation */
87 24397800 : if (old_alloc_sz < new_data_size)
88 : {
89 16643800 : uword n_bytes, req_size = new_data_size;
90 16643800 : void *p = v - data_offset;
91 :
92 16643800 : req_size += CLIB_VECTOR_GROW_BY_ONE ? 0 : n_data_bytes / 2;
93 :
94 16643800 : p = clib_mem_heap_realloc_aligned (vec_get_heap (v), p, req_size,
95 : vec_get_align (v));
96 16645200 : new_alloc_sz = clib_mem_size (p);
97 16645100 : v = p + data_offset;
98 :
99 : /* zero out new allocation */
100 16645100 : n_bytes = new_alloc_sz - old_alloc_sz;
101 16645100 : clib_mem_unpoison (p + old_alloc_sz, n_bytes);
102 16645000 : clib_memset_u8 (p + old_alloc_sz, 0, n_bytes);
103 : }
104 :
105 24398900 : _vec_update_len (v, n_elts, elt_sz, n_data_bytes,
106 : new_alloc_sz - new_data_size);
107 24398800 : return v;
108 : }
109 :
110 : __clib_export void *
111 74361900 : _vec_resize_internal (void *v, uword n_elts, const vec_attr_t *const attr)
112 : {
113 74361900 : uword elt_sz = attr->elt_sz;
114 74361900 : if (PREDICT_TRUE (v != 0))
115 : {
116 74343600 : uword hs = _vec_find (v)->hdr_size * VEC_MIN_ALIGN;
117 74343600 : uword alloc_sz = clib_mem_size (v - hs);
118 74343500 : uword n_data_bytes = elt_sz * n_elts;
119 74343500 : word unused_bytes = alloc_sz - (n_data_bytes + hs);
120 :
121 74343500 : if (PREDICT_TRUE (unused_bytes >= 0))
122 : {
123 57860200 : _vec_update_len (v, n_elts, elt_sz, n_data_bytes, unused_bytes);
124 57860200 : return v;
125 : }
126 : }
127 :
128 : /* this shouled emit tail jump and likely avoid stack usasge inside this
129 : * function */
130 16501600 : return _vec_realloc_internal (v, n_elts, attr);
131 : }
132 :
133 : __clib_export u32
134 0 : vec_len_not_inline (void *v)
135 : {
136 0 : return vec_len (v);
137 : }
138 :
139 : __clib_export void
140 0 : vec_free_not_inline (void *v)
141 : {
142 0 : vec_free (v);
143 0 : }
|