VPP-1506: dump local punts and registered punt sockets
[vpp.git] / src / vppinfra / test_valloc.c
1 /*
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
18 u32
19 vl (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  */
27 uword
28 pe (void *v)
29 {
30   return (pool_elts (v));
31 }
32
33 typedef 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
48 test_main_t test_main;
49
50 clib_error_t *
51 test_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
201 clib_error_t *
202 test_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         ;
222       else if (unformat (i, "check-every-add-del"))
223         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
239 int
240 main (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  */