FD.io VPP  v20.05.1-5-g09f167997
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 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 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 /** \cond */
144 
145 #ifdef TEST
146 
147 #include <stdio.h>
148 
149 void
150 main (int argc, char *argv[])
151 {
152  word n = atoi (argv[1]);
153  word i, *x = 0;
154 
155  typedef struct
156  {
157  word x, y, z;
158  } FOO;
159 
160  FOO *foos = vec_init (FOO, 10), *f;
161 
162  vec_validate (foos, 100);
163  foos[100].x = 99;
164 
165  _vec_len (foos) = 0;
166  for (i = 0; i < n; i++)
167  {
168  vec_add1 (x, i);
169  vec_add2 (foos, f, 1);
170  f->x = 2 * i;
171  f->y = 3 * i;
172  f->z = 4 * i;
173  }
174 
175  {
176  word n = 2;
177  word m = 42;
178  vec_delete (foos, n, m);
179  }
180 
181  {
182  word n = 2;
183  word m = 42;
184  vec_insert (foos, n, m);
185  }
186 
187  vec_free (x);
188  vec_free (foos);
189  exit (0);
190 }
191 #endif
192 /** \endcond */
193 
194 /*
195  * fd.io coding-style-patch-verification: ON
196  *
197  * Local Variables:
198  * eval: (c-set-style "gnu")
199  * End:
200  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
#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:125
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
#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:590
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:628
#define VEC_NUMA_UNSPECIFIED
Definition: mem.h:58
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
i64 word
Definition: types.h:111
static uword vec_header_bytes(uword header_bytes)
Definition: vec_bootstrap.h:79
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header...
Definition: vec.h:753
static void * clib_mem_get_per_cpu_heap(void)
Definition: mem.h:65
#define PREDICT_FALSE(x)
Definition: clib.h:118
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:246
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:852
static void clib_mem_free(void *p)
Definition: mem.h:215
vector header structure
Definition: vec_bootstrap.h:55
static uword clib_mem_is_heap_object(void *p)
Definition: mem.h:207
static void * clib_mem_get_per_numa_heap(u32 numa_id)
Definition: mem.h:81
static void * clib_mem_set_per_cpu_heap(u8 *new_heap)
Definition: mem.h:72
int main(int argc, char **argv)
Definition: health_check.c:24
u64 uword
Definition: types.h:112
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