blob: 970f7f7bfa8893ecc0f77e7677fca0663421f670 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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
Damjan Marionedca8c62021-04-28 17:30:51 +020041#ifndef CLIB_VECTOR_GROW_BY_ONE
42#define CLIB_VECTOR_GROW_BY_ONE 0
43#endif
44
Ed Warnickecb9cada2015-12-08 15:45:58 -070045/* Vector resize operator. Called as needed by various macros such as
46 vec_add1() when we need to allocate memory. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +020047__clib_export void *
Dave Barachc3799992016-08-15 11:12:27 -040048vec_resize_allocate_memory (void *v,
49 word length_increment,
50 uword data_bytes,
Dave Baracha690fdb2020-01-21 12:34:55 -050051 uword header_bytes, uword data_align,
52 uword numa_id)
Ed Warnickecb9cada2015-12-08 15:45:58 -070053{
Dave Barachc3799992016-08-15 11:12:27 -040054 vec_header_t *vh = _vec_find (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -070055 uword old_alloc_bytes, new_alloc_bytes;
Dave Barachc3799992016-08-15 11:12:27 -040056 void *old, *new;
Dave Baracha690fdb2020-01-21 12:34:55 -050057 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058
59 header_bytes = vec_header_bytes (header_bytes);
60
61 data_bytes += header_bytes;
62
Dave Baracha690fdb2020-01-21 12:34:55 -050063 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
64 {
65 oldheap = clib_mem_get_per_cpu_heap ();
66 clib_mem_set_per_cpu_heap (clib_mem_get_per_numa_heap (numa_id));
67 }
68
Dave Barachc3799992016-08-15 11:12:27 -040069 if (!v)
Ed Warnickecb9cada2015-12-08 15:45:58 -070070 {
Dave Barach241e5222016-10-13 10:53:26 -040071 new = clib_mem_alloc_aligned_at_offset (data_bytes, data_align, header_bytes, 1 /* yes, call os_out_of_memory */
72 );
Benoît Ganne9fb6d402019-04-15 15:28:21 +020073 new_alloc_bytes = clib_mem_size (new);
74 CLIB_MEM_UNPOISON (new + data_bytes, new_alloc_bytes - data_bytes);
75 clib_memset (new, 0, new_alloc_bytes);
76 CLIB_MEM_POISON (new + data_bytes, new_alloc_bytes - data_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -070077 v = new + header_bytes;
78 _vec_len (v) = length_increment;
Dave Baracha690fdb2020-01-21 12:34:55 -050079 _vec_numa (v) = numa_id;
80 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
81 clib_mem_set_per_cpu_heap (oldheap);
Ed Warnickecb9cada2015-12-08 15:45:58 -070082 return v;
83 }
84
85 vh->len += length_increment;
86 old = v - header_bytes;
87
88 /* Vector header must start heap object. */
89 ASSERT (clib_mem_is_heap_object (old));
90
91 old_alloc_bytes = clib_mem_size (old);
92
93 /* Need to resize? */
94 if (data_bytes <= old_alloc_bytes)
Benoît Ganne9fb6d402019-04-15 15:28:21 +020095 {
96 CLIB_MEM_UNPOISON (v, data_bytes);
Dave Baracha690fdb2020-01-21 12:34:55 -050097 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
98 clib_mem_set_per_cpu_heap (oldheap);
Benoît Ganne9fb6d402019-04-15 15:28:21 +020099 return v;
100 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700101
Dave Barach98bd7572020-02-10 10:16:40 -0500102#if CLIB_VECTOR_GROW_BY_ONE > 0
103 new_alloc_bytes = data_bytes;
104#else
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 new_alloc_bytes = (old_alloc_bytes * 3) / 2;
106 if (new_alloc_bytes < data_bytes)
107 new_alloc_bytes = data_bytes;
Dave Barach98bd7572020-02-10 10:16:40 -0500108#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109
Dave Barachc3799992016-08-15 11:12:27 -0400110 new =
111 clib_mem_alloc_aligned_at_offset (new_alloc_bytes, data_align,
Dave Barach241e5222016-10-13 10:53:26 -0400112 header_bytes,
113 1 /* yes, call os_out_of_memory */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700114
115 /* FIXME fail gracefully. */
Dave Barachc3799992016-08-15 11:12:27 -0400116 if (!new)
117 clib_panic
118 ("vec_resize fails, length increment %d, data bytes %d, alignment %d",
119 length_increment, data_bytes, data_align);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120
Benoît Ganne9fb6d402019-04-15 15:28:21 +0200121 CLIB_MEM_UNPOISON (old, old_alloc_bytes);
Dave Barach178cf492018-11-13 16:34:13 -0500122 clib_memcpy_fast (new, old, old_alloc_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123 clib_mem_free (old);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124
125 /* Allocator may give a bit of extra room. */
Dave Barach6a5adc32018-07-04 10:56:23 -0400126 new_alloc_bytes = clib_mem_size (new);
127 v = new;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700128
129 /* Zero new memory. */
Benoît Ganne9fb6d402019-04-15 15:28:21 +0200130 CLIB_MEM_UNPOISON (new + data_bytes, new_alloc_bytes - data_bytes);
Florin Coras9e041b12019-03-20 23:16:15 -0700131 memset (v + old_alloc_bytes, 0, new_alloc_bytes - old_alloc_bytes);
Benoît Ganne9fb6d402019-04-15 15:28:21 +0200132 CLIB_MEM_POISON (new + data_bytes, new_alloc_bytes - data_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700133
Dave Baracha690fdb2020-01-21 12:34:55 -0500134 _vec_numa ((v + header_bytes)) = numa_id;
135 if (PREDICT_FALSE (numa_id != VEC_NUMA_UNSPECIFIED))
136 clib_mem_set_per_cpu_heap (oldheap);
137
Ed Warnickecb9cada2015-12-08 15:45:58 -0700138 return v + header_bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400139}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140
Nathan Skrzypczak7ff514b2020-10-21 19:30:48 +0200141__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400142clib_mem_is_vec_h (void *v, uword header_bytes)
143{
144 return clib_mem_is_heap_object (vec_header (v, header_bytes));
145}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146
Dave Barach07619242020-10-18 06:54:31 -0400147__clib_export u32
Dave Barache09ae012020-08-19 06:59:53 -0400148vec_len_not_inline (void *v)
149{
150 return vec_len (v);
151}
152
Dave Barach07619242020-10-18 06:54:31 -0400153__clib_export void
Dave Barache09ae012020-08-19 06:59:53 -0400154vec_free_not_inline (void *v)
155{
156 vec_free (v);
157}
158
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159/** \cond */
160
161#ifdef TEST
162
163#include <stdio.h>
164
Dave Barachc3799992016-08-15 11:12:27 -0400165void
166main (int argc, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167{
168 word n = atoi (argv[1]);
Dave Barachc3799992016-08-15 11:12:27 -0400169 word i, *x = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170
Dave Barachc3799992016-08-15 11:12:27 -0400171 typedef struct
172 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700173 word x, y, z;
174 } FOO;
175
Dave Barachc3799992016-08-15 11:12:27 -0400176 FOO *foos = vec_init (FOO, 10), *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177
178 vec_validate (foos, 100);
179 foos[100].x = 99;
180
181 _vec_len (foos) = 0;
182 for (i = 0; i < n; i++)
183 {
184 vec_add1 (x, i);
185 vec_add2 (foos, f, 1);
Dave Barachc3799992016-08-15 11:12:27 -0400186 f->x = 2 * i;
187 f->y = 3 * i;
188 f->z = 4 * i;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700189 }
190
191 {
192 word n = 2;
193 word m = 42;
194 vec_delete (foos, n, m);
195 }
196
197 {
198 word n = 2;
199 word m = 42;
200 vec_insert (foos, n, m);
201 }
202
203 vec_free (x);
204 vec_free (foos);
205 exit (0);
206}
207#endif
208/** \endcond */
Dave Barachc3799992016-08-15 11:12:27 -0400209
210/*
211 * fd.io coding-style-patch-verification: ON
212 *
213 * Local Variables:
214 * eval: (c-set-style "gnu")
215 * End:
216 */