FD.io VPP  v21.01.1
Vector Packet Processing
vec.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17 
18  Permission is hereby granted, free of charge, to any person obtaining
19  a copy of this software and associated documentation files (the
20  "Software"), to deal in the Software without restriction, including
21  without limitation the rights to use, copy, modify, merge, publish,
22  distribute, sublicense, and/or sell copies of the Software, and to
23  permit persons to whom the Software is furnished to do so, subject to
24  the following conditions:
25 
26  The above copyright notice and this permission notice shall be
27  included in all copies or substantial portions of the Software.
28 
29  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37 
38 #include <vppinfra/vec.h>
39 #include <vppinfra/mem.h>
40 
41 /* Vector resize operator. Called as needed by various macros such as
42  vec_add1() when we need to allocate memory. */
43 __clib_export void *
45  word length_increment,
46  uword data_bytes,
47  uword header_bytes, uword data_align,
48  uword numa_id)
49 {
50  vec_header_t *vh = _vec_find (v);
51  uword old_alloc_bytes, new_alloc_bytes;
52  void *old, *new;
53  void *oldheap;
54 
55  header_bytes = vec_header_bytes (header_bytes);
56 
57  data_bytes += header_bytes;
58 
59  if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
60  {
61  oldheap = clib_mem_get_per_cpu_heap ();
63  }
64 
65  if (!v)
66  {
67  new = clib_mem_alloc_aligned_at_offset (data_bytes, data_align, header_bytes, 1 /* yes, call os_out_of_memory */
68  );
69  new_alloc_bytes = clib_mem_size (new);
70  CLIB_MEM_UNPOISON (new + data_bytes, new_alloc_bytes - data_bytes);
71  clib_memset (new, 0, new_alloc_bytes);
72  CLIB_MEM_POISON (new + data_bytes, new_alloc_bytes - data_bytes);
73  v = new + header_bytes;
74  _vec_len (v) = length_increment;
75  _vec_numa (v) = numa_id;
76  if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
77  clib_mem_set_per_cpu_heap (oldheap);
78  return v;
79  }
80 
81  vh->len += length_increment;
82  old = v - header_bytes;
83 
84  /* Vector header must start heap object. */
86 
87  old_alloc_bytes = clib_mem_size (old);
88 
89  /* Need to resize? */
90  if (data_bytes <= old_alloc_bytes)
91  {
92  CLIB_MEM_UNPOISON (v, data_bytes);
93  if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
94  clib_mem_set_per_cpu_heap (oldheap);
95  return v;
96  }
97 
98 #if CLIB_VECTOR_GROW_BY_ONE > 0
99  new_alloc_bytes = data_bytes;
100 #else
101  new_alloc_bytes = (old_alloc_bytes * 3) / 2;
102  if (new_alloc_bytes < data_bytes)
103  new_alloc_bytes = data_bytes;
104 #endif
105 
106  new =
107  clib_mem_alloc_aligned_at_offset (new_alloc_bytes, data_align,
108  header_bytes,
109  1 /* yes, call os_out_of_memory */ );
110 
111  /* FIXME fail gracefully. */
112  if (!new)
113  clib_panic
114  ("vec_resize fails, length increment %d, data bytes %d, alignment %d",
115  length_increment, data_bytes, data_align);
116 
117  CLIB_MEM_UNPOISON (old, old_alloc_bytes);
118  clib_memcpy_fast (new, old, old_alloc_bytes);
119  clib_mem_free (old);
120 
121  /* Allocator may give a bit of extra room. */
122  new_alloc_bytes = clib_mem_size (new);
123  v = new;
124 
125  /* Zero new memory. */
126  CLIB_MEM_UNPOISON (new + data_bytes, new_alloc_bytes - data_bytes);
127  memset (v + old_alloc_bytes, 0, new_alloc_bytes - old_alloc_bytes);
128  CLIB_MEM_POISON (new + data_bytes, new_alloc_bytes - data_bytes);
129 
130  _vec_numa ((v + header_bytes)) = numa_id;
131  if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
132  clib_mem_set_per_cpu_heap (oldheap);
133 
134  return v + header_bytes;
135 }
136 
137 __clib_export uword
138 clib_mem_is_vec_h (void *v, uword header_bytes)
139 {
140  return clib_mem_is_heap_object (vec_header (v, header_bytes));
141 }
142 
143 __clib_export u32
145 {
146  return vec_len (v);
147 }
148 
149 __clib_export void
151 {
152  vec_free (v);
153 }
154 
155 /** \cond */
156 
157 #ifdef TEST
158 
159 #include <stdio.h>
160 
161 void
162 main (int argc, char *argv[])
163 {
164  word n = atoi (argv[1]);
165  word i, *x = 0;
166 
167  typedef struct
168  {
169  word x, y, z;
170  } FOO;
171 
172  FOO *foos = vec_init (FOO, 10), *f;
173 
174  vec_validate (foos, 100);
175  foos[100].x = 99;
176 
177  _vec_len (foos) = 0;
178  for (i = 0; i < n; i++)
179  {
180  vec_add1 (x, i);
181  vec_add2 (foos, f, 1);
182  f->x = 2 * i;
183  f->y = 3 * i;
184  f->z = 4 * i;
185  }
186 
187  {
188  word n = 2;
189  word m = 42;
190  vec_delete (foos, n, m);
191  }
192 
193  {
194  word n = 2;
195  word m = 42;
196  vec_insert (foos, n, m);
197  }
198 
199  vec_free (x);
200  vec_free (foos);
201  exit (0);
202 }
203 #endif
204 /** \endcond */
205 
206 /*
207  * fd.io coding-style-patch-verification: ON
208  *
209  * Local Variables:
210  * eval: (c-set-style "gnu")
211  * End:
212  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
#define CLIB_MEM_UNPOISON(a, s)
Definition: sanitizer.h:47
static void * clib_mem_alloc_aligned_at_offset(uword size, uword align, uword align_offset, int os_out_of_memory_on_failure)
Definition: mem.h:222
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
static void * clib_mem_set_per_cpu_heap(void *new_heap)
Definition: mem.h:168
#define VEC_NUMA_UNSPECIFIED
Definition: mem.h:158
i64 word
Definition: types.h:111
static uword vec_header_bytes(uword header_bytes)
Definition: vec_bootstrap.h:79
unsigned int u32
Definition: types.h:88
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header...
Definition: vec.h:755
__clib_export void * vec_resize_allocate_memory(void *v, word length_increment, uword data_bytes, uword header_bytes, uword data_align, uword numa_id)
Low-level resize allocation function, usually not called directly.
Definition: vec.c:44
__clib_export uword clib_mem_is_vec_h(void *v, uword header_bytes)
Predicate function, says whether the supplied vector is a clib heap object (general version)...
Definition: vec.c:138
#define PREDICT_FALSE(x)
Definition: clib.h:121
static clib_mem_heap_t * clib_mem_get_per_cpu_heap(void)
Definition: mem.h:161
__clib_export void vec_free_not_inline(void *v)
Definition: vec.c:150
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static uword clib_mem_size(void *p)
Definition: mem.h:343
u32 len
Number of elements in vector (NOT its allocated length).
Definition: vec_bootstrap.h:57
#define ASSERT(truth)
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:854
static void clib_mem_free(void *p)
Definition: mem.h:311
vector header structure
Definition: vec_bootstrap.h:55
static uword clib_mem_is_heap_object(void *p)
Definition: mem.h:303
static void * clib_mem_get_per_numa_heap(u32 numa_id)
Definition: mem.h:177
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int main(int argc, char **argv)
Definition: health_check.c:24
u64 uword
Definition: types.h:112
__clib_export u32 vec_len_not_inline(void *v)
Definition: vec.c:144
static void * vec_header(void *v, uword header_bytes)
Find a user vector header.
Definition: vec_bootstrap.h:92
#define clib_panic(format, args...)
Definition: error.h:72
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
#define CLIB_MEM_POISON(a, s)
Definition: sanitizer.h:46