blob: 6bc36b89ac3b681abe8683d11e410ce1c9d065b5 [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#ifdef CLIB_LINUX_KERNEL
39#include <linux/unistd.h>
40#endif
41
42#ifdef CLIB_UNIX
43#include <unistd.h>
44#include <stdlib.h>
Dave Barachc3799992016-08-15 11:12:27 -040045#include <stdio.h> /* scanf */
Ed Warnickecb9cada2015-12-08 15:45:58 -070046#endif
47
48#include <vppinfra/mheap.h>
49#include <vppinfra/format.h>
50#include <vppinfra/random.h>
51
52static int verbose = 0;
53#define if_verbose(format,args...) \
54 if (verbose) { clib_warning(format, ## args); }
55
Dave Barachc3799992016-08-15 11:12:27 -040056int
57test_mheap_main (unformat_input_t * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -070058{
59 int i, j, k, n_iterations;
Dave Barachc3799992016-08-15 11:12:27 -040060 void *h, *h_mem;
61 uword *objects = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070062 u32 objects_used, really_verbose, n_objects, max_object_size;
63 u32 check_mask, seed, trace, use_vm;
64 u32 print_every = 0;
Dave Barachc3799992016-08-15 11:12:27 -040065 u32 *data;
66 mheap_t *mh;
Ed Warnickecb9cada2015-12-08 15:45:58 -070067
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. */
Dave Barachc3799992016-08-15 11:12:27 -0400104 if (!seed)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 seed = random_default_seed ();
106
Dave Barachc3799992016-08-15 11:12:27 -0400107 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);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111
112 vec_resize (objects, n_objects);
Dave Barachc3799992016-08-15 11:12:27 -0400113 if (vec_bytes (objects)) /* stupid warning be gone */
114 memset (objects, ~0, vec_bytes (objects));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700115 objects_used = 0;
116
117 /* Allocate initial heap. */
118 {
Dave Barachc3799992016-08-15 11:12:27 -0400119 uword size =
120 max_pow2 (2 * n_objects * max_object_size * sizeof (data[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121
122 h_mem = clib_mem_alloc (size);
Dave Barachc3799992016-08-15 11:12:27 -0400123 if (!h_mem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124 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 }
Dave Barachc3799992016-08-15 11:12:27 -0400169
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170 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
Dave Barachc3799992016-08-15 11:12:27 -0400183 data = (void *) h + objects[j];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184 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 {
Dave Barachc3799992016-08-15 11:12:27 -0400200 u32 *data = h + objects[j];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201 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)
Dave Barachc3799992016-08-15 11:12:27 -0400207 fformat (stderr, "iteration %d: %U\n", i, format_mheap, h,
208 really_verbose);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209 }
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
Dave Barachc3799992016-08-15 11:12:27 -0400221int
222main (int argc, char *argv[])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223{
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 */
Dave Barachc3799992016-08-15 11:12:27 -0400235
236/*
237 * fd.io coding-style-patch-verification: ON
238 *
239 * Local Variables:
240 * eval: (c-set-style "gnu")
241 * End:
242 */