blob: ea786db92d6d630d3356b90508f05fa1de9fc4a4 [file] [log] [blame]
Dave Barach6484a682018-01-24 19:20:55 -05001/*
2 * Copyright (c) 2018 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#include <vppinfra/valloc.h>
17
18u32
19vl (void *p)
20{
21 return vec_len (p);
22}
23
24/*
25 * GDB callable function: pe - call pool_elts - number of elements in a pool
26 */
27uword
28pe (void *v)
29{
30 return (pool_elts (v));
31}
32
33typedef struct
34{
35 u32 seed;
36 uword baseva;
37 uword size;
38 uword *basevas;
39 u8 *item_in_table;
40 u32 nitems;
41 u32 niter;
42 u32 item_size;
43 int check_every_add_del;
44 clib_valloc_main_t valloc_main;
45 int verbose;
46} test_main_t;
47
48test_main_t test_main;
49
50clib_error_t *
51test_valloc (test_main_t * tm)
52{
53 clib_valloc_chunk_t _ip, *ip = &_ip;
54 uword baseva;
55 uword *p;
56 int i, j, index;
57 u32 currently_in_table;
58 u32 found;
59
60 ip->baseva = 0x20000000;
61 ip->size = 1024;
62
63 clib_valloc_init (&tm->valloc_main, ip, 1 /* lock */ );
64
65 ip->baseva = 0x20000000 + 1024;
66 ip->size = 1024 * 1024 * 1024 - 1024;
67 clib_valloc_add_chunk (&tm->valloc_main, ip);
68
69 fformat (stdout, "Allocate %d items...\n", tm->nitems);
70 for (i = 0; i < tm->nitems; i++)
71 {
72 baseva = clib_valloc_alloc (&tm->valloc_main, 1024,
73 1 /* fail:os_out_of_memory */ );
74 vec_add1 (tm->basevas, baseva);
75 vec_add1 (tm->item_in_table, 1);
76 }
77
78 fformat (stdout, "Perform %d random add/delete operations...\n", tm->niter);
79
80 for (i = 0; i < tm->niter; i++)
81 {
82 index = random_u32 (&tm->seed) % tm->nitems;
83 /* Swap state of random entry */
84 if (tm->item_in_table[index])
85 {
86 if (0)
87 fformat (stdout, "free [%d] %llx\n", index, tm->basevas[index]);
88 clib_valloc_free (&tm->valloc_main, tm->basevas[index]);
89 tm->item_in_table[index] = 0;
90 tm->basevas[index] = ~0;
91 }
92 else
93 {
94 baseva = clib_valloc_alloc (&tm->valloc_main, 1024,
95 1 /* fail:os_out_of_memory */ );
96 tm->basevas[index] = baseva;
97 tm->item_in_table[index] = 1;
98 if (0)
99 fformat (stdout, "alloc [%d] %llx\n", index, tm->basevas[index]);
100 }
101
102 /* Check our work... */
103 if (tm->check_every_add_del)
104 {
105 for (j = 0; j < tm->nitems; j++)
106 {
107 if (tm->item_in_table[j])
108 {
109 p = hash_get ((&tm->valloc_main)->chunk_index_by_baseva,
110 tm->basevas[j]);
111 if (p)
112 {
113 ip =
114 pool_elt_at_index ((&tm->valloc_main)->chunks, p[0]);
115 ASSERT (ip->baseva == tm->basevas[j]);
116 ASSERT (ip->flags & CLIB_VALLOC_BUSY);
117 }
118 }
119 else
120 {
121 p = hash_get ((&tm->valloc_main)->chunk_index_by_baseva,
122 tm->basevas[j]);
123 /* Have to check, it's OK for the block to have been fused */
124 if (p)
125 {
126 ip =
127 pool_elt_at_index ((&tm->valloc_main)->chunks, p[0]);
128 if ((ip->flags & CLIB_VALLOC_BUSY))
129 {
130 fformat (stdout, "BUG: baseva %llx chunk %d busy\n",
131 tm->basevas[j], p[0]);
132 fformat (stdout, "%U\n", format_valloc,
133 &tm->valloc_main, 1 /* verbose */ );
134 ASSERT ((ip->flags & CLIB_VALLOC_BUSY) == 0);
135 }
136 }
137 }
138 }
139 }
140 }
141
142 currently_in_table = 0;
143
144 for (i = 0; i < tm->nitems; i++)
145 {
146 currently_in_table += tm->item_in_table[i];
147 }
148
149 fformat (stdout, "Check that %d items in table can be found...\n",
150 currently_in_table);
151
152 found = 0;
153
154 for (i = 0; i < tm->nitems; i++)
155 {
156 if (tm->item_in_table[i])
157 {
158 p = hash_get ((&tm->valloc_main)->chunk_index_by_baseva,
159 tm->basevas[i]);
160 if (p)
161 {
162 ip = pool_elt_at_index ((&tm->valloc_main)->chunks, p[0]);
163 ASSERT (ip->baseva == tm->basevas[i]);
164 ASSERT (ip->flags & CLIB_VALLOC_BUSY);
165 }
166 found++;
167 }
168 else
169 {
170 p = hash_get ((&tm->valloc_main)->chunk_index_by_baseva,
171 tm->basevas[i]);
172 /* Have to check, it's OK for the block to have been fused */
173 if (p)
174 {
175 ip = pool_elt_at_index ((&tm->valloc_main)->chunks, p[0]);
176 if ((ip->flags & CLIB_VALLOC_BUSY))
177 {
178 fformat (stdout, "BUG: baseva %llx chunk %d busy\n",
179 tm->basevas[i], p[0]);
180 fformat (stdout, "%U\n", format_valloc,
181 &tm->valloc_main, 1 /* verbose */ );
182 ASSERT ((ip->flags & CLIB_VALLOC_BUSY) == 0);
183 }
184 }
185 }
186 }
187
188 fformat (stdout, "Found %d items in table...\n", found);
189
190 for (i = 0; i < tm->nitems; i++)
191 {
192 if (tm->item_in_table[i])
193 clib_valloc_free (&tm->valloc_main, tm->basevas[i]);
194 }
195
196 fformat (stdout, "%U", format_valloc, &tm->valloc_main, 1 /* verbose */ );
197
198 return 0;
199}
200
201clib_error_t *
202test_valloc_main (unformat_input_t * i)
203{
204 test_main_t *tm = &test_main;
205 clib_error_t *error;
206
207 tm->seed = 0xdeaddabe;
208 tm->nitems = 5;
209 tm->niter = 100;
210 tm->item_size = 1024;
211
212 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
213 {
214 if (unformat (i, "seed %u", &tm->seed))
215 ;
216 else if (unformat (i, "nitems %u", &tm->nitems))
217 ;
218 else if (unformat (i, "niter %u", &tm->niter))
219 ;
220 else if (unformat (i, "item-size %u", &tm->item_size))
221 ;
Dave Barach8d6ef602018-01-30 14:12:31 -0500222 else if (unformat (i, "check-every-add-del"))
Dave Barach6484a682018-01-24 19:20:55 -0500223 tm->check_every_add_del = 1;
224 else if (unformat (i, "verbose %d", &tm->verbose))
225 ;
226 else if (unformat (i, "verbose"))
227 tm->verbose = 1;
228 else
229 return clib_error_return (0, "unknown input '%U'",
230 format_unformat_error, i);
231 }
232
233 error = test_valloc (tm);
234
235 return error;
236}
237
238#ifdef CLIB_UNIX
239int
240main (int argc, char *argv[])
241{
242 unformat_input_t i;
243 int rv = 0;
244 clib_error_t *error;
245
246 clib_mem_init (0, 3ULL << 30);
247
248 unformat_init_command_line (&i, argv);
249 error = test_valloc_main (&i);
250 if (error)
251 {
252 clib_error_report (error);
253 rv = 1;
254 }
255 unformat_free (&i);
256
257 return rv;
258}
259#endif /* CLIB_UNIX */
260
261/*
262 * fd.io coding-style-patch-verification: ON
263 *
264 * Local Variables:
265 * eval: (c-set-style "gnu")
266 * End:
267 */