1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2018 Arm Limited
3 */
4
5 #include <stdio.h>
6 #include <stdbool.h>
7 #include <inttypes.h>
8 #include <rte_pause.h>
9 #include <rte_rcu_qsbr.h>
10 #include <rte_hash.h>
11 #include <rte_hash_crc.h>
12 #include <rte_malloc.h>
13 #include <rte_cycles.h>
14 #include <unistd.h>
15
16 #include "test.h"
17
18 /* Check condition and return an error if true. */
19 static uint16_t enabled_core_ids[RTE_MAX_LCORE];
20 static unsigned int num_cores;
21
22 static uint32_t *keys;
23 #define TOTAL_ENTRY (1024 * 8)
24 #define COUNTER_VALUE 4096
25 static uint32_t *hash_data[TOTAL_ENTRY];
26 static volatile uint8_t writer_done;
27 static volatile uint8_t all_registered;
28 static volatile RTE_ATOMIC(uint32_t) thr_id;
29
30 static struct rte_rcu_qsbr *t[RTE_MAX_LCORE];
31 static struct rte_hash *h;
32 static char hash_name[8];
33 static RTE_ATOMIC(uint64_t) updates;
34 static RTE_ATOMIC(uint64_t) checks;
35 static RTE_ATOMIC(uint64_t) update_cycles;
36 static RTE_ATOMIC(uint64_t) check_cycles;
37
38 /* Scale down results to 1000 operations to support lower
39 * granularity clocks.
40 */
41 #define RCU_SCALE_DOWN 1000
42
43 /* Simple way to allocate thread ids in 0 to RTE_MAX_LCORE space */
44 static inline uint32_t
alloc_thread_id(void)45 alloc_thread_id(void)
46 {
47 uint32_t tmp_thr_id;
48
49 tmp_thr_id = rte_atomic_fetch_add_explicit(&thr_id, 1, rte_memory_order_relaxed);
50 if (tmp_thr_id >= RTE_MAX_LCORE)
51 printf("Invalid thread id %u\n", tmp_thr_id);
52
53 return tmp_thr_id;
54 }
55
56 static int
test_rcu_qsbr_reader_perf(void * arg)57 test_rcu_qsbr_reader_perf(void *arg)
58 {
59 bool writer_present = (bool)arg;
60 uint32_t thread_id = alloc_thread_id();
61 uint64_t loop_cnt = 0;
62 uint64_t begin, cycles;
63
64 /* Register for report QS */
65 rte_rcu_qsbr_thread_register(t[0], thread_id);
66 /* Make the thread online */
67 rte_rcu_qsbr_thread_online(t[0], thread_id);
68
69 begin = rte_rdtsc_precise();
70
71 if (writer_present) {
72 while (!writer_done) {
73 /* Update quiescent state counter */
74 rte_rcu_qsbr_quiescent(t[0], thread_id);
75 loop_cnt++;
76 }
77 } else {
78 while (loop_cnt < 100000000) {
79 /* Update quiescent state counter */
80 rte_rcu_qsbr_quiescent(t[0], thread_id);
81 loop_cnt++;
82 }
83 }
84
85 cycles = rte_rdtsc_precise() - begin;
86 rte_atomic_fetch_add_explicit(&update_cycles, cycles, rte_memory_order_relaxed);
87 rte_atomic_fetch_add_explicit(&updates, loop_cnt, rte_memory_order_relaxed);
88
89 /* Make the thread offline */
90 rte_rcu_qsbr_thread_offline(t[0], thread_id);
91 /* Unregister before exiting to avoid writer from waiting */
92 rte_rcu_qsbr_thread_unregister(t[0], thread_id);
93
94 return 0;
95 }
96
97 static int
test_rcu_qsbr_writer_perf(void * arg)98 test_rcu_qsbr_writer_perf(void *arg)
99 {
100 bool wait = (bool)arg;
101 uint64_t token = 0;
102 uint64_t loop_cnt = 0;
103 uint64_t begin, cycles;
104
105 begin = rte_rdtsc_precise();
106
107 do {
108 /* Start the quiescent state query process */
109 if (wait)
110 token = rte_rcu_qsbr_start(t[0]);
111
112 /* Check quiescent state status */
113 rte_rcu_qsbr_check(t[0], token, wait);
114 loop_cnt++;
115 } while (loop_cnt < 20000000);
116
117 cycles = rte_rdtsc_precise() - begin;
118 rte_atomic_fetch_add_explicit(&check_cycles, cycles, rte_memory_order_relaxed);
119 rte_atomic_fetch_add_explicit(&checks, loop_cnt, rte_memory_order_relaxed);
120 return 0;
121 }
122
123 /*
124 * Perf test: Reader/writer
125 * Single writer, Multiple Readers, Single QS var, Non-Blocking rcu_qsbr_check
126 */
127 static int
test_rcu_qsbr_perf(void)128 test_rcu_qsbr_perf(void)
129 {
130 size_t sz;
131 unsigned int i, tmp_num_cores;
132
133 writer_done = 0;
134
135 rte_atomic_store_explicit(&updates, 0, rte_memory_order_relaxed);
136 rte_atomic_store_explicit(&update_cycles, 0, rte_memory_order_relaxed);
137 rte_atomic_store_explicit(&checks, 0, rte_memory_order_relaxed);
138 rte_atomic_store_explicit(&check_cycles, 0, rte_memory_order_relaxed);
139
140 printf("\nPerf Test: %d Readers/1 Writer('wait' in qsbr_check == true)\n",
141 num_cores - 1);
142
143 rte_atomic_store_explicit(&thr_id, 0, rte_memory_order_seq_cst);
144
145 if (all_registered == 1)
146 tmp_num_cores = num_cores - 1;
147 else
148 tmp_num_cores = RTE_MAX_LCORE;
149
150 sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
151 t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
152 RTE_CACHE_LINE_SIZE);
153 /* QS variable is initialized */
154 rte_rcu_qsbr_init(t[0], tmp_num_cores);
155
156 /* Reader threads are launched */
157 for (i = 0; i < num_cores - 1; i++)
158 rte_eal_remote_launch(test_rcu_qsbr_reader_perf, (void *)1,
159 enabled_core_ids[i]);
160
161 /* Writer thread is launched */
162 rte_eal_remote_launch(test_rcu_qsbr_writer_perf,
163 (void *)1, enabled_core_ids[i]);
164
165 /* Wait for the writer thread */
166 rte_eal_wait_lcore(enabled_core_ids[i]);
167 writer_done = 1;
168
169 /* Wait until all readers have exited */
170 rte_eal_mp_wait_lcore();
171
172 printf("Total quiescent state updates = %"PRIi64"\n",
173 rte_atomic_load_explicit(&updates, rte_memory_order_relaxed));
174 printf("Cycles per %d quiescent state updates: %"PRIi64"\n",
175 RCU_SCALE_DOWN,
176 rte_atomic_load_explicit(&update_cycles, rte_memory_order_relaxed) /
177 (rte_atomic_load_explicit(&updates, rte_memory_order_relaxed) / RCU_SCALE_DOWN));
178 printf("Total RCU checks = %"PRIi64"\n", rte_atomic_load_explicit(&checks,
179 rte_memory_order_relaxed));
180 printf("Cycles per %d checks: %"PRIi64"\n", RCU_SCALE_DOWN,
181 rte_atomic_load_explicit(&check_cycles, rte_memory_order_relaxed) /
182 (rte_atomic_load_explicit(&checks, rte_memory_order_relaxed) / RCU_SCALE_DOWN));
183
184 rte_free(t[0]);
185
186 return 0;
187 }
188
189 /*
190 * Perf test: Readers
191 * Single writer, Multiple readers, Single QS variable
192 */
193 static int
test_rcu_qsbr_rperf(void)194 test_rcu_qsbr_rperf(void)
195 {
196 size_t sz;
197 unsigned int i, tmp_num_cores;
198
199 rte_atomic_store_explicit(&updates, 0, rte_memory_order_relaxed);
200 rte_atomic_store_explicit(&update_cycles, 0, rte_memory_order_relaxed);
201
202 rte_atomic_store_explicit(&thr_id, 0, rte_memory_order_seq_cst);
203
204 printf("\nPerf Test: %d Readers\n", num_cores);
205
206 if (all_registered == 1)
207 tmp_num_cores = num_cores;
208 else
209 tmp_num_cores = RTE_MAX_LCORE;
210
211 sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
212 t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
213 RTE_CACHE_LINE_SIZE);
214 /* QS variable is initialized */
215 rte_rcu_qsbr_init(t[0], tmp_num_cores);
216
217 /* Reader threads are launched */
218 for (i = 0; i < num_cores; i++)
219 rte_eal_remote_launch(test_rcu_qsbr_reader_perf, NULL,
220 enabled_core_ids[i]);
221
222 /* Wait until all readers have exited */
223 rte_eal_mp_wait_lcore();
224
225 printf("Total quiescent state updates = %"PRIi64"\n",
226 rte_atomic_load_explicit(&updates, rte_memory_order_relaxed));
227 printf("Cycles per %d quiescent state updates: %"PRIi64"\n",
228 RCU_SCALE_DOWN,
229 rte_atomic_load_explicit(&update_cycles, rte_memory_order_relaxed) /
230 (rte_atomic_load_explicit(&updates, rte_memory_order_relaxed) / RCU_SCALE_DOWN));
231
232 rte_free(t[0]);
233
234 return 0;
235 }
236
237 /*
238 * Perf test:
239 * Multiple writer, Single QS variable, Non-blocking rcu_qsbr_check
240 */
241 static int
test_rcu_qsbr_wperf(void)242 test_rcu_qsbr_wperf(void)
243 {
244 size_t sz;
245 unsigned int i;
246
247 rte_atomic_store_explicit(&checks, 0, rte_memory_order_relaxed);
248 rte_atomic_store_explicit(&check_cycles, 0, rte_memory_order_relaxed);
249
250 rte_atomic_store_explicit(&thr_id, 0, rte_memory_order_seq_cst);
251
252 printf("\nPerf test: %d Writers ('wait' in qsbr_check == false)\n",
253 num_cores);
254
255 /* Number of readers does not matter for QS variable in this test
256 * case as no reader will be registered.
257 */
258 sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
259 t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
260 RTE_CACHE_LINE_SIZE);
261 /* QS variable is initialized */
262 rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
263
264 /* Writer threads are launched */
265 for (i = 0; i < num_cores; i++)
266 rte_eal_remote_launch(test_rcu_qsbr_writer_perf,
267 (void *)0, enabled_core_ids[i]);
268
269 /* Wait until all readers have exited */
270 rte_eal_mp_wait_lcore();
271
272 printf("Total RCU checks = %"PRIi64"\n", rte_atomic_load_explicit(&checks,
273 rte_memory_order_relaxed));
274 printf("Cycles per %d checks: %"PRIi64"\n", RCU_SCALE_DOWN,
275 rte_atomic_load_explicit(&check_cycles, rte_memory_order_relaxed) /
276 (rte_atomic_load_explicit(&checks, rte_memory_order_relaxed) / RCU_SCALE_DOWN));
277
278 rte_free(t[0]);
279
280 return 0;
281 }
282
283 /*
284 * RCU test cases using rte_hash data structure.
285 */
286 static int
test_rcu_qsbr_hash_reader(void * arg)287 test_rcu_qsbr_hash_reader(void *arg)
288 {
289 struct rte_rcu_qsbr *temp;
290 struct rte_hash *hash = NULL;
291 int i;
292 uint64_t loop_cnt = 0;
293 uint64_t begin, cycles;
294 uint32_t thread_id = alloc_thread_id();
295 uint8_t read_type = (uint8_t)((uintptr_t)arg);
296 uint32_t *pdata;
297
298 temp = t[read_type];
299 hash = h;
300
301 rte_rcu_qsbr_thread_register(temp, thread_id);
302
303 begin = rte_rdtsc_precise();
304
305 do {
306 rte_rcu_qsbr_thread_online(temp, thread_id);
307 for (i = 0; i < TOTAL_ENTRY; i++) {
308 rte_rcu_qsbr_lock(temp, thread_id);
309 if (rte_hash_lookup_data(hash, keys + i,
310 (void **)&pdata) != -ENOENT) {
311 pdata[thread_id] = 0;
312 while (pdata[thread_id] < COUNTER_VALUE)
313 pdata[thread_id]++;
314 }
315 rte_rcu_qsbr_unlock(temp, thread_id);
316 }
317 /* Update quiescent state counter */
318 rte_rcu_qsbr_quiescent(temp, thread_id);
319 rte_rcu_qsbr_thread_offline(temp, thread_id);
320 loop_cnt++;
321 } while (!writer_done);
322
323 cycles = rte_rdtsc_precise() - begin;
324 rte_atomic_fetch_add_explicit(&update_cycles, cycles, rte_memory_order_relaxed);
325 rte_atomic_fetch_add_explicit(&updates, loop_cnt, rte_memory_order_relaxed);
326
327 rte_rcu_qsbr_thread_unregister(temp, thread_id);
328
329 return 0;
330 }
331
init_hash(void)332 static struct rte_hash *init_hash(void)
333 {
334 int i;
335 struct rte_hash *hash = NULL;
336
337 snprintf(hash_name, 8, "hash");
338 struct rte_hash_parameters hash_params = {
339 .entries = TOTAL_ENTRY,
340 .key_len = sizeof(uint32_t),
341 .hash_func_init_val = 0,
342 .socket_id = rte_socket_id(),
343 .hash_func = rte_hash_crc,
344 .extra_flag =
345 RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF,
346 .name = hash_name,
347 };
348
349 hash = rte_hash_create(&hash_params);
350 if (hash == NULL) {
351 printf("Hash create Failed\n");
352 return NULL;
353 }
354
355 for (i = 0; i < TOTAL_ENTRY; i++) {
356 hash_data[i] = rte_zmalloc(NULL,
357 sizeof(uint32_t) * RTE_MAX_LCORE, 0);
358 if (hash_data[i] == NULL) {
359 printf("No memory\n");
360 return NULL;
361 }
362 }
363 keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_ENTRY, 0);
364 if (keys == NULL) {
365 printf("No memory\n");
366 return NULL;
367 }
368
369 for (i = 0; i < TOTAL_ENTRY; i++)
370 keys[i] = i;
371
372 for (i = 0; i < TOTAL_ENTRY; i++) {
373 if (rte_hash_add_key_data(hash, keys + i,
374 (void *)((uintptr_t)hash_data[i])) < 0) {
375 printf("Hash key add Failed #%d\n", i);
376 return NULL;
377 }
378 }
379 return hash;
380 }
381
382 /*
383 * Functional test:
384 * Single writer, Single QS variable Single QSBR query, Blocking rcu_qsbr_check
385 */
386 static int
test_rcu_qsbr_sw_sv_1qs(void)387 test_rcu_qsbr_sw_sv_1qs(void)
388 {
389 uint64_t token, begin, cycles;
390 size_t sz;
391 unsigned int i, j, tmp_num_cores;
392 int32_t pos;
393
394 writer_done = 0;
395
396 rte_atomic_store_explicit(&updates, 0, rte_memory_order_relaxed);
397 rte_atomic_store_explicit(&update_cycles, 0, rte_memory_order_relaxed);
398 rte_atomic_store_explicit(&checks, 0, rte_memory_order_relaxed);
399 rte_atomic_store_explicit(&check_cycles, 0, rte_memory_order_relaxed);
400
401 rte_atomic_store_explicit(&thr_id, 0, rte_memory_order_seq_cst);
402
403 printf("\nPerf test: 1 writer, %d readers, 1 QSBR variable, 1 QSBR Query, Blocking QSBR Check\n", num_cores);
404
405 if (all_registered == 1)
406 tmp_num_cores = num_cores;
407 else
408 tmp_num_cores = RTE_MAX_LCORE;
409
410 sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
411 t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
412 RTE_CACHE_LINE_SIZE);
413 /* QS variable is initialized */
414 rte_rcu_qsbr_init(t[0], tmp_num_cores);
415
416 /* Shared data structure created */
417 h = init_hash();
418 if (h == NULL) {
419 printf("Hash init failed\n");
420 goto error;
421 }
422
423 /* Reader threads are launched */
424 for (i = 0; i < num_cores; i++)
425 rte_eal_remote_launch(test_rcu_qsbr_hash_reader, NULL,
426 enabled_core_ids[i]);
427
428 begin = rte_rdtsc_precise();
429
430 for (i = 0; i < TOTAL_ENTRY; i++) {
431 /* Delete elements from the shared data structure */
432 pos = rte_hash_del_key(h, keys + i);
433 if (pos < 0) {
434 printf("Delete key failed #%d\n", keys[i]);
435 goto error;
436 }
437 /* Start the quiescent state query process */
438 token = rte_rcu_qsbr_start(t[0]);
439
440 /* Check the quiescent state status */
441 rte_rcu_qsbr_check(t[0], token, true);
442 for (j = 0; j < tmp_num_cores; j++) {
443 if (hash_data[i][j] != COUNTER_VALUE &&
444 hash_data[i][j] != 0) {
445 printf("Reader thread ID %u did not complete #%d = %d\n",
446 j, i, hash_data[i][j]);
447 goto error;
448 }
449 }
450
451 if (rte_hash_free_key_with_position(h, pos) < 0) {
452 printf("Failed to free the key #%d\n", keys[i]);
453 goto error;
454 }
455 rte_free(hash_data[i]);
456 hash_data[i] = NULL;
457 }
458
459 cycles = rte_rdtsc_precise() - begin;
460 rte_atomic_fetch_add_explicit(&check_cycles, cycles, rte_memory_order_relaxed);
461 rte_atomic_fetch_add_explicit(&checks, i, rte_memory_order_relaxed);
462
463 writer_done = 1;
464
465 /* Wait and check return value from reader threads */
466 for (i = 0; i < num_cores; i++)
467 if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
468 goto error;
469 rte_hash_free(h);
470 rte_free(keys);
471
472 printf("Following numbers include calls to rte_hash functions\n");
473 printf("Cycles per 1 quiescent state update(online/update/offline): %"PRIi64"\n",
474 rte_atomic_load_explicit(&update_cycles, rte_memory_order_relaxed) /
475 rte_atomic_load_explicit(&updates, rte_memory_order_relaxed));
476
477 printf("Cycles per 1 check(start, check): %"PRIi64"\n\n",
478 rte_atomic_load_explicit(&check_cycles, rte_memory_order_relaxed) /
479 rte_atomic_load_explicit(&checks, rte_memory_order_relaxed));
480
481 rte_free(t[0]);
482
483 return 0;
484
485 error:
486 writer_done = 1;
487 /* Wait until all readers have exited */
488 rte_eal_mp_wait_lcore();
489
490 rte_hash_free(h);
491 rte_free(keys);
492 for (i = 0; i < TOTAL_ENTRY; i++)
493 rte_free(hash_data[i]);
494
495 rte_free(t[0]);
496
497 return -1;
498 }
499
500 /*
501 * Functional test:
502 * Single writer, Single QS variable, Single QSBR query,
503 * Non-blocking rcu_qsbr_check
504 */
505 static int
test_rcu_qsbr_sw_sv_1qs_non_blocking(void)506 test_rcu_qsbr_sw_sv_1qs_non_blocking(void)
507 {
508 uint64_t token, begin, cycles;
509 int ret;
510 size_t sz;
511 unsigned int i, j, tmp_num_cores;
512 int32_t pos;
513
514 writer_done = 0;
515
516 printf("Perf test: 1 writer, %d readers, 1 QSBR variable, 1 QSBR Query, Non-Blocking QSBR check\n", num_cores);
517
518 rte_atomic_store_explicit(&thr_id, 0, rte_memory_order_relaxed);
519
520 if (all_registered == 1)
521 tmp_num_cores = num_cores;
522 else
523 tmp_num_cores = RTE_MAX_LCORE;
524
525 sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
526 t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
527 RTE_CACHE_LINE_SIZE);
528 /* QS variable is initialized */
529 rte_rcu_qsbr_init(t[0], tmp_num_cores);
530
531 /* Shared data structure created */
532 h = init_hash();
533 if (h == NULL) {
534 printf("Hash init failed\n");
535 goto error;
536 }
537
538 /* Reader threads are launched */
539 for (i = 0; i < num_cores; i++)
540 rte_eal_remote_launch(test_rcu_qsbr_hash_reader, NULL,
541 enabled_core_ids[i]);
542
543 begin = rte_rdtsc_precise();
544
545 for (i = 0; i < TOTAL_ENTRY; i++) {
546 /* Delete elements from the shared data structure */
547 pos = rte_hash_del_key(h, keys + i);
548 if (pos < 0) {
549 printf("Delete key failed #%d\n", keys[i]);
550 goto error;
551 }
552 /* Start the quiescent state query process */
553 token = rte_rcu_qsbr_start(t[0]);
554
555 /* Check the quiescent state status */
556 do {
557 ret = rte_rcu_qsbr_check(t[0], token, false);
558 } while (ret == 0);
559 for (j = 0; j < tmp_num_cores; j++) {
560 if (hash_data[i][j] != COUNTER_VALUE &&
561 hash_data[i][j] != 0) {
562 printf("Reader thread ID %u did not complete #%d = %d\n",
563 j, i, hash_data[i][j]);
564 goto error;
565 }
566 }
567
568 if (rte_hash_free_key_with_position(h, pos) < 0) {
569 printf("Failed to free the key #%d\n", keys[i]);
570 goto error;
571 }
572 rte_free(hash_data[i]);
573 hash_data[i] = NULL;
574 }
575
576 cycles = rte_rdtsc_precise() - begin;
577 rte_atomic_fetch_add_explicit(&check_cycles, cycles, rte_memory_order_relaxed);
578 rte_atomic_fetch_add_explicit(&checks, i, rte_memory_order_relaxed);
579
580 writer_done = 1;
581 /* Wait and check return value from reader threads */
582 for (i = 0; i < num_cores; i++)
583 if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
584 goto error;
585 rte_hash_free(h);
586 rte_free(keys);
587
588 printf("Following numbers include calls to rte_hash functions\n");
589 printf("Cycles per 1 quiescent state update(online/update/offline): %"PRIi64"\n",
590 rte_atomic_load_explicit(&update_cycles, rte_memory_order_relaxed) /
591 rte_atomic_load_explicit(&updates, rte_memory_order_relaxed));
592
593 printf("Cycles per 1 check(start, check): %"PRIi64"\n\n",
594 rte_atomic_load_explicit(&check_cycles, rte_memory_order_relaxed) /
595 rte_atomic_load_explicit(&checks, rte_memory_order_relaxed));
596
597 rte_free(t[0]);
598
599 return 0;
600
601 error:
602 writer_done = 1;
603 /* Wait until all readers have exited */
604 rte_eal_mp_wait_lcore();
605
606 rte_hash_free(h);
607 rte_free(keys);
608 for (i = 0; i < TOTAL_ENTRY; i++)
609 rte_free(hash_data[i]);
610
611 rte_free(t[0]);
612
613 return -1;
614 }
615
616 static int
test_rcu_qsbr_main(void)617 test_rcu_qsbr_main(void)
618 {
619 uint16_t core_id;
620
621 if (RTE_EXEC_ENV_IS_WINDOWS)
622 return TEST_SKIPPED;
623
624 if (rte_lcore_count() < 3) {
625 printf("Not enough cores for rcu_qsbr_perf_autotest, expecting at least 3\n");
626 return TEST_SKIPPED;
627 }
628
629 rte_atomic_store_explicit(&updates, 0, rte_memory_order_relaxed);
630 rte_atomic_store_explicit(&update_cycles, 0, rte_memory_order_relaxed);
631 rte_atomic_store_explicit(&checks, 0, rte_memory_order_relaxed);
632 rte_atomic_store_explicit(&check_cycles, 0, rte_memory_order_relaxed);
633
634 num_cores = 0;
635 RTE_LCORE_FOREACH_WORKER(core_id) {
636 enabled_core_ids[num_cores] = core_id;
637 num_cores++;
638 }
639
640 printf("Number of cores provided = %d\n", num_cores);
641 printf("Perf test with all reader threads registered\n");
642 printf("--------------------------------------------\n");
643 all_registered = 1;
644
645 if (test_rcu_qsbr_perf() < 0)
646 goto test_fail;
647
648 if (test_rcu_qsbr_rperf() < 0)
649 goto test_fail;
650
651 if (test_rcu_qsbr_wperf() < 0)
652 goto test_fail;
653
654 if (test_rcu_qsbr_sw_sv_1qs() < 0)
655 goto test_fail;
656
657 if (test_rcu_qsbr_sw_sv_1qs_non_blocking() < 0)
658 goto test_fail;
659
660 /* Make sure the actual number of cores provided is less than
661 * RTE_MAX_LCORE. This will allow for some threads not
662 * to be registered on the QS variable.
663 */
664 if (num_cores >= RTE_MAX_LCORE) {
665 printf("Test failed! number of cores provided should be less than %d\n",
666 RTE_MAX_LCORE);
667 goto test_fail;
668 }
669
670 printf("Perf test with some of reader threads registered\n");
671 printf("------------------------------------------------\n");
672 all_registered = 0;
673
674 if (test_rcu_qsbr_perf() < 0)
675 goto test_fail;
676
677 if (test_rcu_qsbr_rperf() < 0)
678 goto test_fail;
679
680 if (test_rcu_qsbr_wperf() < 0)
681 goto test_fail;
682
683 if (test_rcu_qsbr_sw_sv_1qs() < 0)
684 goto test_fail;
685
686 if (test_rcu_qsbr_sw_sv_1qs_non_blocking() < 0)
687 goto test_fail;
688
689 printf("\n");
690
691 return 0;
692
693 test_fail:
694 return -1;
695 }
696
697 REGISTER_PERF_TEST(rcu_qsbr_perf_autotest, test_rcu_qsbr_main);
698