dpdk: Add support for Mellanox ConnectX-4 devices
[vpp.git] / src / vppinfra / test_mheap.c
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 #ifdef CLIB_LINUX_KERNEL
39 #include <linux/unistd.h>
40 #endif
41
42 #ifdef CLIB_UNIX
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <stdio.h>              /* scanf */
46 #endif
47
48 #include <vppinfra/mheap.h>
49 #include <vppinfra/format.h>
50 #include <vppinfra/random.h>
51
52 static int verbose = 0;
53 #define if_verbose(format,args...) \
54   if (verbose) { clib_warning(format, ## args); }
55
56 int
57 test_mheap_main (unformat_input_t * input)
58 {
59   int i, j, k, n_iterations;
60   void *h, *h_mem;
61   uword *objects = 0;
62   u32 objects_used, really_verbose, n_objects, max_object_size;
63   u32 check_mask, seed, trace, use_vm;
64   u32 print_every = 0;
65   u32 *data;
66   mheap_t *mh;
67
68   /* Validation flags. */
69   check_mask = 0;
70 #define CHECK_VALIDITY 1
71 #define CHECK_DATA     2
72 #define CHECK_ALIGN    4
73
74   n_iterations = 10;
75   seed = 0;
76   max_object_size = 100;
77   n_objects = 1000;
78   trace = 0;
79   really_verbose = 0;
80   use_vm = 0;
81
82   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
83     {
84       if (0 == unformat (input, "iter %d", &n_iterations)
85           && 0 == unformat (input, "count %d", &n_objects)
86           && 0 == unformat (input, "size %d", &max_object_size)
87           && 0 == unformat (input, "seed %d", &seed)
88           && 0 == unformat (input, "print %d", &print_every)
89           && 0 == unformat (input, "validdata %|",
90                             &check_mask, CHECK_DATA | CHECK_VALIDITY)
91           && 0 == unformat (input, "valid %|",
92                             &check_mask, CHECK_VALIDITY)
93           && 0 == unformat (input, "verbose %=", &really_verbose, 1)
94           && 0 == unformat (input, "trace %=", &trace, 1)
95           && 0 == unformat (input, "vm %=", &use_vm, 1)
96           && 0 == unformat (input, "align %|", &check_mask, CHECK_ALIGN))
97         {
98           clib_warning ("unknown input `%U'", format_unformat_error, input);
99           return 1;
100         }
101     }
102
103   /* Zero seed means use default. */
104   if (!seed)
105     seed = random_default_seed ();
106
107   if_verbose
108     ("testing %d iterations, %d %saligned objects, max. size %d, seed %d",
109      n_iterations, n_objects, (check_mask & CHECK_ALIGN) ? "randomly " : "un",
110      max_object_size, seed);
111
112   vec_resize (objects, n_objects);
113   if (vec_bytes (objects))      /* stupid warning be gone */
114     memset (objects, ~0, vec_bytes (objects));
115   objects_used = 0;
116
117   /* Allocate initial heap. */
118   {
119     uword size =
120       max_pow2 (2 * n_objects * max_object_size * sizeof (data[0]));
121
122     h_mem = clib_mem_alloc (size);
123     if (!h_mem)
124       return 0;
125
126     h = mheap_alloc (h_mem, size);
127   }
128
129   if (trace)
130     mheap_trace (h, trace);
131
132   mh = mheap_header (h);
133
134   if (use_vm)
135     mh->flags &= ~MHEAP_FLAG_DISABLE_VM;
136   else
137     mh->flags |= MHEAP_FLAG_DISABLE_VM;
138
139   if (check_mask & CHECK_VALIDITY)
140     mh->flags |= MHEAP_FLAG_VALIDATE;
141
142   for (i = 0; i < n_iterations; i++)
143     {
144       while (1)
145         {
146           j = random_u32 (&seed) % vec_len (objects);
147           if (objects[j] != ~0 || i + objects_used < n_iterations)
148             break;
149         }
150
151       if (objects[j] != ~0)
152         {
153           mheap_put (h, objects[j]);
154           objects_used--;
155           objects[j] = ~0;
156         }
157       else
158         {
159           uword size, align, align_offset;
160
161           size = (random_u32 (&seed) % max_object_size) * sizeof (data[0]);
162           align = align_offset = 0;
163           if (check_mask & CHECK_ALIGN)
164             {
165               align = 1 << (random_u32 (&seed) % 10);
166               align_offset = round_pow2 (random_u32 (&seed) & (align - 1),
167                                          sizeof (u32));
168             }
169
170           h = mheap_get_aligned (h, size, align, align_offset, &objects[j]);
171
172           if (align > 0)
173             ASSERT (0 == ((objects[j] + align_offset) & (align - 1)));
174
175           ASSERT (objects[j] != ~0);
176           objects_used++;
177
178           /* Set newly allocated object with test data. */
179           if (check_mask & CHECK_DATA)
180             {
181               uword len;
182
183               data = (void *) h + objects[j];
184               len = mheap_len (h, data);
185
186               ASSERT (size <= mheap_data_bytes (h, objects[j]));
187
188               data[0] = len;
189               for (k = 1; k < len; k++)
190                 data[k] = objects[j] + k;
191             }
192         }
193
194       /* Verify that all used objects have correct test data. */
195       if (check_mask & 2)
196         {
197           for (j = 0; j < vec_len (objects); j++)
198             if (objects[j] != ~0)
199               {
200                 u32 *data = h + objects[j];
201                 uword len = data[0];
202                 for (k = 1; k < len; k++)
203                   ASSERT (data[k] == objects[j] + k);
204               }
205         }
206       if (print_every != 0 && i > 0 && (i % print_every) == 0)
207         fformat (stderr, "iteration %d: %U\n", i, format_mheap, h,
208                  really_verbose);
209     }
210
211   if (verbose)
212     fformat (stderr, "%U\n", format_mheap, h, really_verbose);
213   mheap_free (h);
214   clib_mem_free (h_mem);
215   vec_free (objects);
216
217   return 0;
218 }
219
220 #ifdef CLIB_UNIX
221 int
222 main (int argc, char *argv[])
223 {
224   unformat_input_t i;
225   int ret;
226
227   verbose = (argc > 1);
228   unformat_init_command_line (&i, argv);
229   ret = test_mheap_main (&i);
230   unformat_free (&i);
231
232   return ret;
233 }
234 #endif /* CLIB_UNIX */
235
236 /*
237  * fd.io coding-style-patch-verification: ON
238  *
239  * Local Variables:
240  * eval: (c-set-style "gnu")
241  * End:
242  */