]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/processor-trace/libipt/test/src/ptunit-block_cache.c
Copy libevent sources to contrib
[FreeBSD/FreeBSD.git] / contrib / processor-trace / libipt / test / src / ptunit-block_cache.c
1 /*
2  * Copyright (c) 2016-2018, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "ptunit_threads.h"
30
31 #include "pt_block_cache.h"
32
33 #include <string.h>
34
35
36 /* A test fixture optionally providing a block cache and automatically freeing
37  * the cache.
38  */
39 struct bcache_fixture {
40         /* Threading support. */
41         struct ptunit_thrd_fixture thrd;
42
43         /* The cache - it will be freed automatically. */
44         struct pt_block_cache *bcache;
45
46         /* The test fixture initialization and finalization functions. */
47         struct ptunit_result (*init)(struct bcache_fixture *);
48         struct ptunit_result (*fini)(struct bcache_fixture *);
49 };
50
51 enum {
52         /* The number of entries in fixture-provided caches. */
53         bfix_nentries = 0x10000,
54
55 #if defined(FEATURE_THREADS)
56
57         /* The number of additional threads to use for stress testing. */
58         bfix_threads = 3,
59
60 #endif /* defined(FEATURE_THREADS) */
61
62         /* The number of iterations in stress testing. */
63         bfix_iterations = 0x10
64 };
65
66 static struct ptunit_result cfix_init(struct bcache_fixture *bfix)
67 {
68         ptu_test(ptunit_thrd_init, &bfix->thrd);
69
70         bfix->bcache = NULL;
71
72         return ptu_passed();
73 }
74
75 static struct ptunit_result bfix_init(struct bcache_fixture *bfix)
76 {
77         ptu_test(cfix_init, bfix);
78
79         bfix->bcache = pt_bcache_alloc(bfix_nentries);
80         ptu_ptr(bfix->bcache);
81
82         return ptu_passed();
83 }
84
85 static struct ptunit_result bfix_fini(struct bcache_fixture *bfix)
86 {
87         int thrd;
88
89         ptu_test(ptunit_thrd_fini, &bfix->thrd);
90
91         for (thrd = 0; thrd < bfix->thrd.nthreads; ++thrd)
92                 ptu_int_eq(bfix->thrd.result[thrd], 0);
93
94         pt_bcache_free(bfix->bcache);
95
96         return ptu_passed();
97 }
98
99 static struct ptunit_result bcache_entry_size(void)
100 {
101         ptu_uint_eq(sizeof(struct pt_bcache_entry), sizeof(uint32_t));
102
103         return ptu_passed();
104 }
105
106 static struct ptunit_result bcache_size(void)
107 {
108         ptu_uint_le(sizeof(struct pt_block_cache),
109                     2 * sizeof(struct pt_bcache_entry));
110
111         return ptu_passed();
112 }
113
114 static struct ptunit_result free_null(void)
115 {
116         pt_bcache_free(NULL);
117
118         return ptu_passed();
119 }
120
121 static struct ptunit_result add_null(void)
122 {
123         struct pt_bcache_entry bce;
124         int errcode;
125
126         memset(&bce, 0, sizeof(bce));
127
128         errcode = pt_bcache_add(NULL, 0ull, bce);
129         ptu_int_eq(errcode, -pte_internal);
130
131         return ptu_passed();
132 }
133
134 static struct ptunit_result lookup_null(void)
135 {
136         struct pt_bcache_entry bce;
137         struct pt_block_cache bcache;
138         int errcode;
139
140         errcode = pt_bcache_lookup(&bce, NULL, 0ull);
141         ptu_int_eq(errcode, -pte_internal);
142
143         errcode = pt_bcache_lookup(NULL, &bcache, 0ull);
144         ptu_int_eq(errcode, -pte_internal);
145
146         return ptu_passed();
147 }
148
149 static struct ptunit_result alloc(struct bcache_fixture *bfix)
150 {
151         bfix->bcache = pt_bcache_alloc(0x10000ull);
152         ptu_ptr(bfix->bcache);
153
154         return ptu_passed();
155 }
156
157 static struct ptunit_result alloc_min(struct bcache_fixture *bfix)
158 {
159         bfix->bcache = pt_bcache_alloc(1ull);
160         ptu_ptr(bfix->bcache);
161
162         return ptu_passed();
163 }
164
165 static struct ptunit_result alloc_too_big(struct bcache_fixture *bfix)
166 {
167         bfix->bcache = pt_bcache_alloc(UINT32_MAX + 1ull);
168         ptu_null(bfix->bcache);
169
170         return ptu_passed();
171 }
172
173 static struct ptunit_result alloc_zero(struct bcache_fixture *bfix)
174 {
175         bfix->bcache = pt_bcache_alloc(0ull);
176         ptu_null(bfix->bcache);
177
178         return ptu_passed();
179 }
180
181 static struct ptunit_result initially_empty(struct bcache_fixture *bfix)
182 {
183         uint64_t index;
184
185         for (index = 0; index < bfix_nentries; ++index) {
186                 struct pt_bcache_entry bce;
187                 int status;
188
189                 memset(&bce, 0xff, sizeof(bce));
190
191                 status = pt_bcache_lookup(&bce, bfix->bcache, index);
192                 ptu_int_eq(status, 0);
193
194                 status = pt_bce_is_valid(bce);
195                 ptu_int_eq(status, 0);
196         }
197
198         return ptu_passed();
199 }
200
201 static struct ptunit_result add_bad_index(struct bcache_fixture *bfix)
202 {
203         struct pt_bcache_entry bce;
204         int errcode;
205
206         memset(&bce, 0, sizeof(bce));
207
208         errcode = pt_bcache_add(bfix->bcache, bfix_nentries, bce);
209         ptu_int_eq(errcode, -pte_internal);
210
211         return ptu_passed();
212 }
213
214 static struct ptunit_result lookup_bad_index(struct bcache_fixture *bfix)
215 {
216         struct pt_bcache_entry bce;
217         int errcode;
218
219         errcode = pt_bcache_lookup(&bce, bfix->bcache, bfix_nentries);
220         ptu_int_eq(errcode, -pte_internal);
221
222         return ptu_passed();
223 }
224
225 static struct ptunit_result add(struct bcache_fixture *bfix, uint64_t index)
226 {
227         struct pt_bcache_entry bce, exp;
228         int errcode;
229
230         memset(&bce, 0xff, sizeof(bce));
231         memset(&exp, 0x00, sizeof(exp));
232
233         exp.ninsn = 1;
234         exp.displacement = 7;
235         exp.mode = ptem_64bit;
236         exp.qualifier = ptbq_decode;
237         exp.isize = 7;
238
239         errcode = pt_bcache_add(bfix->bcache, index, exp);
240         ptu_int_eq(errcode, 0);
241
242         errcode = pt_bcache_lookup(&bce, bfix->bcache, index);
243         ptu_int_eq(errcode, 0);
244
245         ptu_uint_eq(bce.ninsn, exp.ninsn);
246         ptu_int_eq(bce.displacement, exp.displacement);
247         ptu_uint_eq(pt_bce_exec_mode(bce), pt_bce_exec_mode(exp));
248         ptu_uint_eq(pt_bce_qualifier(bce), pt_bce_qualifier(exp));
249         ptu_uint_eq(bce.isize, exp.isize);
250
251         return ptu_passed();
252 }
253
254 static int worker(void *arg)
255 {
256         struct pt_bcache_entry exp;
257         struct pt_block_cache *bcache;
258         uint64_t iter, index;
259
260         bcache = arg;
261         if (!bcache)
262                 return -pte_internal;
263
264         memset(&exp, 0x00, sizeof(exp));
265         exp.ninsn = 5;
266         exp.displacement = 28;
267         exp.mode = ptem_64bit;
268         exp.qualifier = ptbq_again;
269         exp.isize = 3;
270
271         for (index = 0; index < bfix_nentries; ++index) {
272                 for (iter = 0; iter < bfix_iterations; ++iter) {
273                         struct pt_bcache_entry bce;
274                         int errcode;
275
276                         memset(&bce, 0xff, sizeof(bce));
277
278                         errcode = pt_bcache_lookup(&bce, bcache, index);
279                         if (errcode < 0)
280                                 return errcode;
281
282                         if (!pt_bce_is_valid(bce)) {
283                                 errcode = pt_bcache_add(bcache, index, exp);
284                                 if (errcode < 0)
285                                         return errcode;
286                         }
287
288                         errcode = pt_bcache_lookup(&bce, bcache, index);
289                         if (errcode < 0)
290                                 return errcode;
291
292                         if (!pt_bce_is_valid(bce))
293                                 return -pte_nosync;
294
295                         if (bce.ninsn != exp.ninsn)
296                                 return -pte_nosync;
297
298                         if (bce.displacement != exp.displacement)
299                                 return -pte_nosync;
300
301                         if (pt_bce_exec_mode(bce) != pt_bce_exec_mode(exp))
302                                 return -pte_nosync;
303
304                         if (pt_bce_qualifier(bce) != pt_bce_qualifier(exp))
305                                 return -pte_nosync;
306
307                         if (bce.isize != exp.isize)
308                                 return -pte_nosync;
309                 }
310         }
311
312         return 0;
313 }
314
315 static struct ptunit_result stress(struct bcache_fixture *bfix)
316 {
317         int errcode;
318
319 #if defined(FEATURE_THREADS)
320         {
321                 int thrd;
322
323                 for (thrd = 0; thrd < bfix_threads; ++thrd)
324                         ptu_test(ptunit_thrd_create, &bfix->thrd, worker,
325                                  bfix->bcache);
326         }
327 #endif /* defined(FEATURE_THREADS) */
328
329         errcode = worker(bfix->bcache);
330         ptu_int_eq(errcode, 0);
331
332         return ptu_passed();
333 }
334
335 int main(int argc, char **argv)
336 {
337         struct bcache_fixture bfix, cfix;
338         struct ptunit_suite suite;
339
340         bfix.init = bfix_init;
341         bfix.fini = bfix_fini;
342
343         cfix.init = cfix_init;
344         cfix.fini = bfix_fini;
345
346         suite = ptunit_mk_suite(argc, argv);
347
348         ptu_run(suite, bcache_entry_size);
349         ptu_run(suite, bcache_size);
350
351         ptu_run(suite, free_null);
352         ptu_run(suite, add_null);
353         ptu_run(suite, lookup_null);
354
355         ptu_run_f(suite, alloc, cfix);
356         ptu_run_f(suite, alloc_min, cfix);
357         ptu_run_f(suite, alloc_too_big, cfix);
358         ptu_run_f(suite, alloc_zero, cfix);
359
360         ptu_run_f(suite, initially_empty, bfix);
361
362         ptu_run_f(suite, add_bad_index, bfix);
363         ptu_run_f(suite, lookup_bad_index, bfix);
364
365         ptu_run_fp(suite, add, bfix, 0ull);
366         ptu_run_fp(suite, add, bfix, bfix_nentries - 1ull);
367         ptu_run_f(suite, stress, bfix);
368
369         return ptunit_report(&suite);
370 }