]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/app/test/test_hash_readwrite_lf.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / app / test / test_hash_readwrite_lf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Arm Limited
3 */
4
5 #include <inttypes.h>
6 #include <locale.h>
7
8 #include <rte_cycles.h>
9 #include <rte_hash.h>
10 #include <rte_hash_crc.h>
11 #include <rte_jhash.h>
12 #include <rte_launch.h>
13 #include <rte_malloc.h>
14 #include <rte_random.h>
15 #include <rte_spinlock.h>
16
17 #include "test.h"
18
19 #ifndef RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF
20 #define RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF 0
21 #endif
22
23 #define BULK_LOOKUP_SIZE 32
24
25 #define RUN_WITH_HTM_DISABLED 0
26
27 #if (RUN_WITH_HTM_DISABLED)
28
29 #define TOTAL_ENTRY (5*1024)
30 #define TOTAL_INSERT (5*1024)
31
32 #else
33
34 #define TOTAL_ENTRY (4*1024*1024)
35 #define TOTAL_INSERT (4*1024*1024)
36
37 #endif
38
39 #define READ_FAIL 1
40 #define READ_PASS_NO_KEY_SHIFTS 2
41 #define READ_PASS_SHIFT_PATH 4
42 #define READ_PASS_NON_SHIFT_PATH 8
43 #define BULK_LOOKUP 16
44 #define READ_PASS_KEY_SHIFTS_EXTBKT 32
45
46 #define WRITE_NO_KEY_SHIFT 0
47 #define WRITE_KEY_SHIFT 1
48 #define WRITE_EXT_BKT 2
49
50 #define NUM_TEST 3
51 unsigned int rwc_core_cnt[NUM_TEST] = {1, 2, 4};
52
53 struct rwc_perf {
54 uint32_t w_no_ks_r_hit[2][NUM_TEST];
55 uint32_t w_no_ks_r_miss[2][NUM_TEST];
56 uint32_t w_ks_r_hit_nsp[2][NUM_TEST];
57 uint32_t w_ks_r_hit_sp[2][NUM_TEST];
58 uint32_t w_ks_r_miss[2][NUM_TEST];
59 uint32_t multi_rw[NUM_TEST - 1][2][NUM_TEST];
60 uint32_t w_ks_r_hit_extbkt[2][NUM_TEST];
61 };
62
63 static struct rwc_perf rwc_lf_results, rwc_non_lf_results;
64
65 struct {
66 uint32_t *keys;
67 uint32_t *keys_no_ks;
68 uint32_t *keys_ks;
69 uint32_t *keys_absent;
70 uint32_t *keys_shift_path;
71 uint32_t *keys_non_shift_path;
72 uint32_t *keys_ext_bkt;
73 uint32_t *keys_ks_extbkt;
74 uint32_t count_keys_no_ks;
75 uint32_t count_keys_ks;
76 uint32_t count_keys_absent;
77 uint32_t count_keys_shift_path;
78 uint32_t count_keys_non_shift_path;
79 uint32_t count_keys_extbkt;
80 uint32_t count_keys_ks_extbkt;
81 uint32_t single_insert;
82 struct rte_hash *h;
83 } tbl_rwc_test_param;
84
85 static rte_atomic64_t gread_cycles;
86 static rte_atomic64_t greads;
87
88 static volatile uint8_t writer_done;
89 static volatile uint8_t multi_writer_done[4];
90
91 uint16_t enabled_core_ids[RTE_MAX_LCORE];
92
93 uint8_t *scanned_bkts;
94
95 static inline uint16_t
96 get_short_sig(const hash_sig_t hash)
97 {
98 return hash >> 16;
99 }
100
101 static inline uint32_t
102 get_prim_bucket_index(__attribute__((unused)) const struct rte_hash *h,
103 const hash_sig_t hash)
104 {
105 uint32_t num_buckets;
106 uint32_t bucket_bitmask;
107 num_buckets = rte_align32pow2(TOTAL_ENTRY) / 8;
108 bucket_bitmask = num_buckets - 1;
109 return hash & bucket_bitmask;
110 }
111
112 static inline uint32_t
113 get_alt_bucket_index(__attribute__((unused)) const struct rte_hash *h,
114 uint32_t cur_bkt_idx, uint16_t sig)
115 {
116 uint32_t num_buckets;
117 uint32_t bucket_bitmask;
118 num_buckets = rte_align32pow2(TOTAL_ENTRY) / 8;
119 bucket_bitmask = num_buckets - 1;
120 return (cur_bkt_idx ^ sig) & bucket_bitmask;
121 }
122
123
124 static inline int
125 get_enabled_cores_list(void)
126 {
127 uint32_t i = 0;
128 uint16_t core_id;
129 uint32_t max_cores = rte_lcore_count();
130 for (core_id = 0; core_id < RTE_MAX_LCORE && i < max_cores; core_id++) {
131 if (rte_lcore_is_enabled(core_id)) {
132 enabled_core_ids[i] = core_id;
133 i++;
134 }
135 }
136
137 if (i != max_cores) {
138 printf("Number of enabled cores in list is different from "
139 "number given by rte_lcore_count()\n");
140 return -1;
141 }
142 return 0;
143 }
144
145 static inline int
146 check_bucket(uint32_t bkt_idx, uint32_t key)
147 {
148 uint32_t iter;
149 uint32_t prev_iter;
150 uint32_t diff;
151 uint32_t count = 0;
152 const void *next_key;
153 void *next_data;
154
155 /* Temporary bucket to hold the keys */
156 uint32_t keys_in_bkt[8];
157
158 iter = bkt_idx * 8;
159 prev_iter = iter;
160 while (rte_hash_iterate(tbl_rwc_test_param.h,
161 &next_key, &next_data, &iter) >= 0) {
162
163 /* Check for duplicate entries */
164 if (*(const uint32_t *)next_key == key)
165 return 1;
166
167 /* Identify if there is any free entry in the bucket */
168 diff = iter - prev_iter;
169 if (diff > 1)
170 break;
171
172 prev_iter = iter;
173 keys_in_bkt[count] = *(const uint32_t *)next_key;
174 count++;
175
176 /* All entries in the bucket are occupied */
177 if (count == 8) {
178
179 /*
180 * Check if bucket was not scanned before, to avoid
181 * duplicate keys.
182 */
183 if (scanned_bkts[bkt_idx] == 0) {
184 /*
185 * Since this bucket (pointed to by bkt_idx) is
186 * full, it is likely that key(s) in this
187 * bucket will be on the shift path, when
188 * collision occurs. Thus, add it to
189 * keys_shift_path.
190 */
191 memcpy(tbl_rwc_test_param.keys_shift_path +
192 tbl_rwc_test_param.count_keys_shift_path
193 , keys_in_bkt, 32);
194 tbl_rwc_test_param.count_keys_shift_path += 8;
195 scanned_bkts[bkt_idx] = 1;
196 }
197 return -1;
198 }
199 }
200 return 0;
201 }
202
203 static int
204 generate_keys(void)
205 {
206 uint32_t *keys = NULL;
207 uint32_t *keys_no_ks = NULL;
208 uint32_t *keys_ks = NULL;
209 uint32_t *keys_absent = NULL;
210 uint32_t *keys_non_shift_path = NULL;
211 uint32_t *keys_ext_bkt = NULL;
212 uint32_t *keys_ks_extbkt = NULL;
213 uint32_t *found = NULL;
214 uint32_t count_keys_no_ks = 0;
215 uint32_t count_keys_ks = 0;
216 uint32_t count_keys_extbkt = 0;
217 uint32_t i;
218
219 /*
220 * keys will consist of a) keys whose addition to the hash table
221 * will result in shifting of the existing keys to their alternate
222 * locations b) keys whose addition to the hash table will not result
223 * in shifting of the existing keys.
224 */
225 keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
226 if (keys == NULL) {
227 printf("RTE_MALLOC failed\n");
228 goto err;
229 }
230
231 /*
232 * keys_no_ks (no key-shifts): Subset of 'keys' - consists of keys that
233 * will NOT result in shifting of the existing keys to their alternate
234 * locations. Roughly around 900K keys.
235 */
236 keys_no_ks = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
237 if (keys_no_ks == NULL) {
238 printf("RTE_MALLOC failed\n");
239 goto err;
240 }
241
242 /*
243 * keys_ks (key-shifts): Subset of 'keys' - consists of keys that will
244 * result in shifting of the existing keys to their alternate locations.
245 * Roughly around 146K keys. There might be repeating keys. More code is
246 * required to filter out these keys which will complicate the test case
247 */
248 keys_ks = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
249 if (keys_ks == NULL) {
250 printf("RTE_MALLOC failed\n");
251 goto err;
252 }
253
254 /* Used to identify keys not inserted in the hash table */
255 found = rte_zmalloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
256 if (found == NULL) {
257 printf("RTE_MALLOC failed\n");
258 goto err;
259 }
260
261 /*
262 * This consist of keys not inserted to the hash table.
263 * Used to test perf of lookup on keys that do not exist in the table.
264 */
265 keys_absent = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
266 if (keys_absent == NULL) {
267 printf("RTE_MALLOC failed\n");
268 goto err;
269 }
270
271 /*
272 * This consist of keys which are likely to be on the shift
273 * path (i.e. being moved to alternate location), when collision occurs
274 * on addition of a key to an already full primary bucket.
275 * Used to test perf of lookup on keys that are on the shift path.
276 */
277 tbl_rwc_test_param.keys_shift_path = rte_malloc(NULL, sizeof(uint32_t) *
278 TOTAL_INSERT, 0);
279 if (tbl_rwc_test_param.keys_shift_path == NULL) {
280 printf("RTE_MALLOC failed\n");
281 goto err;
282 }
283
284 /*
285 * This consist of keys which are never on the shift
286 * path (i.e. being moved to alternate location), when collision occurs
287 * on addition of a key to an already full primary bucket.
288 * Used to test perf of lookup on keys that are not on the shift path.
289 */
290 keys_non_shift_path = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT,
291 0);
292 if (keys_non_shift_path == NULL) {
293 printf("RTE_MALLOC failed\n");
294 goto err;
295 }
296
297 /*
298 * This consist of keys which will be stored in extended buckets
299 */
300 keys_ext_bkt = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
301 if (keys_ext_bkt == NULL) {
302 printf("RTE_MALLOC failed\n");
303 goto err;
304 }
305
306 /*
307 * This consist of keys which when deleted causes shifting of keys
308 * in extended buckets to respective secondary buckets
309 */
310 keys_ks_extbkt = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
311 if (keys_ks_extbkt == NULL) {
312 printf("RTE_MALLOC failed\n");
313 goto err;
314 }
315
316 hash_sig_t sig;
317 uint32_t prim_bucket_idx;
318 uint32_t sec_bucket_idx;
319 uint16_t short_sig;
320 uint32_t num_buckets;
321 num_buckets = rte_align32pow2(TOTAL_ENTRY) / 8;
322 int ret;
323
324 /*
325 * Used to mark bkts in which at least one key was shifted to its
326 * alternate location
327 */
328 scanned_bkts = rte_malloc(NULL, sizeof(uint8_t) * num_buckets, 0);
329 if (scanned_bkts == NULL) {
330 printf("RTE_MALLOC failed\n");
331 goto err;
332 }
333
334 tbl_rwc_test_param.keys = keys;
335 tbl_rwc_test_param.keys_no_ks = keys_no_ks;
336 tbl_rwc_test_param.keys_ks = keys_ks;
337 tbl_rwc_test_param.keys_absent = keys_absent;
338 tbl_rwc_test_param.keys_non_shift_path = keys_non_shift_path;
339 tbl_rwc_test_param.keys_ext_bkt = keys_ext_bkt;
340 tbl_rwc_test_param.keys_ks_extbkt = keys_ks_extbkt;
341 /* Generate keys by adding previous two keys, neglect overflow */
342 printf("Generating keys...\n");
343 keys[0] = 0;
344 keys[1] = 1;
345 for (i = 2; i < TOTAL_INSERT; i++)
346 keys[i] = keys[i-1] + keys[i-2];
347
348 /* Segregate keys into keys_no_ks and keys_ks */
349 for (i = 0; i < TOTAL_INSERT; i++) {
350 /* Check if primary bucket has space.*/
351 sig = rte_hash_hash(tbl_rwc_test_param.h,
352 tbl_rwc_test_param.keys+i);
353 prim_bucket_idx = get_prim_bucket_index(tbl_rwc_test_param.h,
354 sig);
355 ret = check_bucket(prim_bucket_idx, keys[i]);
356 if (ret < 0) {
357 /*
358 * Primary bucket is full, this key will result in
359 * shifting of the keys to their alternate locations.
360 */
361 keys_ks[count_keys_ks] = keys[i];
362 count_keys_ks++;
363 } else if (ret == 0) {
364 /*
365 * Primary bucket has space, this key will not result in
366 * shifting of the keys. Hence, add key to the table.
367 */
368 ret = rte_hash_add_key_data(tbl_rwc_test_param.h,
369 keys+i,
370 (void *)((uintptr_t)i));
371 if (ret < 0) {
372 printf("writer failed %"PRIu32"\n", i);
373 break;
374 }
375 keys_no_ks[count_keys_no_ks] = keys[i];
376 count_keys_no_ks++;
377 }
378 }
379
380 for (i = 0; i < count_keys_no_ks; i++) {
381 /*
382 * Identify keys in keys_no_ks with value less than
383 * 4M (HTM enabled) OR 5K (HTM disabled)
384 */
385 if (keys_no_ks[i] < TOTAL_INSERT)
386 found[keys_no_ks[i]]++;
387 }
388
389 for (i = 0; i < count_keys_ks; i++) {
390 /*
391 * Identify keys in keys_ks with value less than
392 * 4M (HTM enabled) OR 5K (HTM disabled)
393 */
394 if (keys_ks[i] < TOTAL_INSERT)
395 found[keys_ks[i]]++;
396 }
397
398 uint32_t count_keys_absent = 0;
399 for (i = 0; i < TOTAL_INSERT; i++) {
400 /*
401 * Identify missing keys between 0 and
402 * 4M (HTM enabled) OR 5K (HTM disabled)
403 */
404 if (found[i] == 0)
405 keys_absent[count_keys_absent++] = i;
406 }
407
408 /* Find keys that will not be on the shift path */
409 uint32_t iter;
410 const void *next_key;
411 void *next_data;
412 uint32_t count = 0;
413 for (i = 0; i < num_buckets; i++) {
414 /* Check bucket for no keys shifted to alternate locations */
415 if (scanned_bkts[i] == 0) {
416 iter = i * 8;
417 while (rte_hash_iterate(tbl_rwc_test_param.h,
418 &next_key, &next_data, &iter) >= 0) {
419
420 /* Check if key belongs to the current bucket */
421 if (i >= (iter-1)/8)
422 keys_non_shift_path[count++]
423 = *(const uint32_t *)next_key;
424 else
425 break;
426 }
427 }
428 }
429
430 tbl_rwc_test_param.count_keys_no_ks = count_keys_no_ks;
431 tbl_rwc_test_param.count_keys_ks = count_keys_ks;
432 tbl_rwc_test_param.count_keys_absent = count_keys_absent;
433 tbl_rwc_test_param.count_keys_non_shift_path = count;
434
435 memset(scanned_bkts, 0, num_buckets);
436 count = 0;
437 /* Find keys that will be in extended buckets */
438 for (i = 0; i < count_keys_ks; i++) {
439 ret = rte_hash_add_key(tbl_rwc_test_param.h, keys_ks + i);
440 if (ret < 0) {
441 /* Key will be added to ext bkt */
442 keys_ext_bkt[count_keys_extbkt++] = keys_ks[i];
443 /* Sec bkt to be added to keys_ks_extbkt */
444 sig = rte_hash_hash(tbl_rwc_test_param.h,
445 tbl_rwc_test_param.keys_ks + i);
446 prim_bucket_idx = get_prim_bucket_index(
447 tbl_rwc_test_param.h, sig);
448 short_sig = get_short_sig(sig);
449 sec_bucket_idx = get_alt_bucket_index(
450 tbl_rwc_test_param.h,
451 prim_bucket_idx, short_sig);
452 if (scanned_bkts[sec_bucket_idx] == 0)
453 scanned_bkts[sec_bucket_idx] = 1;
454 }
455 }
456
457 /* Find keys that will shift keys in ext bucket*/
458 for (i = 0; i < num_buckets; i++) {
459 if (scanned_bkts[i] == 1) {
460 iter = i * 8;
461 while (rte_hash_iterate(tbl_rwc_test_param.h,
462 &next_key, &next_data, &iter) >= 0) {
463 /* Check if key belongs to the current bucket */
464 if (i >= (iter-1)/8)
465 keys_ks_extbkt[count++]
466 = *(const uint32_t *)next_key;
467 else
468 break;
469 }
470 }
471 }
472
473 tbl_rwc_test_param.count_keys_ks_extbkt = count;
474 tbl_rwc_test_param.count_keys_extbkt = count_keys_extbkt;
475
476 printf("\nCount of keys NOT causing shifting of existing keys to "
477 "alternate location: %d\n", tbl_rwc_test_param.count_keys_no_ks);
478 printf("\nCount of keys causing shifting of existing keys to alternate "
479 "locations: %d\n\n", tbl_rwc_test_param.count_keys_ks);
480 printf("Count of absent keys that will never be added to the hash "
481 "table: %d\n\n", tbl_rwc_test_param.count_keys_absent);
482 printf("Count of keys likely to be on the shift path: %d\n\n",
483 tbl_rwc_test_param.count_keys_shift_path);
484 printf("Count of keys not likely to be on the shift path: %d\n\n",
485 tbl_rwc_test_param.count_keys_non_shift_path);
486 printf("Count of keys in extended buckets: %d\n\n",
487 tbl_rwc_test_param.count_keys_extbkt);
488 printf("Count of keys shifting keys in ext buckets: %d\n\n",
489 tbl_rwc_test_param.count_keys_ks_extbkt);
490
491 rte_free(found);
492 rte_hash_free(tbl_rwc_test_param.h);
493 return 0;
494
495 err:
496 rte_free(keys);
497 rte_free(keys_no_ks);
498 rte_free(keys_ks);
499 rte_free(keys_absent);
500 rte_free(found);
501 rte_free(tbl_rwc_test_param.keys_shift_path);
502 rte_free(keys_ext_bkt);
503 rte_free(keys_ks_extbkt);
504 rte_free(scanned_bkts);
505 return -1;
506 }
507
508 static int
509 init_params(int rwc_lf, int use_jhash, int htm, int ext_bkt)
510 {
511 struct rte_hash *handle;
512
513 struct rte_hash_parameters hash_params = {
514 .entries = TOTAL_ENTRY,
515 .key_len = sizeof(uint32_t),
516 .hash_func_init_val = 0,
517 .socket_id = rte_socket_id(),
518 };
519
520 if (use_jhash)
521 hash_params.hash_func = rte_jhash;
522 else
523 hash_params.hash_func = rte_hash_crc;
524
525 if (rwc_lf)
526 hash_params.extra_flag =
527 RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |
528 RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
529 else if (htm)
530 hash_params.extra_flag =
531 RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT |
532 RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY |
533 RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
534 else
535 hash_params.extra_flag =
536 RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY |
537 RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
538
539 if (ext_bkt)
540 hash_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
541
542 hash_params.name = "tests";
543
544 handle = rte_hash_create(&hash_params);
545 if (handle == NULL) {
546 printf("hash creation failed");
547 return -1;
548 }
549
550 tbl_rwc_test_param.h = handle;
551 return 0;
552 }
553
554 static int
555 test_rwc_reader(__attribute__((unused)) void *arg)
556 {
557 uint32_t i, j;
558 int ret;
559 uint64_t begin, cycles;
560 uint32_t loop_cnt = 0;
561 uint8_t read_type = (uint8_t)((uintptr_t)arg);
562 uint32_t read_cnt;
563 uint32_t *keys;
564 uint32_t extra_keys;
565 int32_t *pos;
566 void *temp_a[BULK_LOOKUP_SIZE];
567
568 /* Used to identify keys not inserted in the hash table */
569 pos = rte_malloc(NULL, sizeof(uint32_t) * BULK_LOOKUP_SIZE, 0);
570 if (pos == NULL) {
571 printf("RTE_MALLOC failed\n");
572 return -1;
573 }
574
575 if (read_type & READ_FAIL) {
576 keys = tbl_rwc_test_param.keys_absent;
577 read_cnt = tbl_rwc_test_param.count_keys_absent;
578 } else if (read_type & READ_PASS_NO_KEY_SHIFTS) {
579 keys = tbl_rwc_test_param.keys_no_ks;
580 read_cnt = tbl_rwc_test_param.count_keys_no_ks;
581 } else if (read_type & READ_PASS_SHIFT_PATH) {
582 keys = tbl_rwc_test_param.keys_shift_path;
583 read_cnt = tbl_rwc_test_param.count_keys_shift_path;
584 } else if (read_type & READ_PASS_KEY_SHIFTS_EXTBKT) {
585 keys = tbl_rwc_test_param.keys_ext_bkt;
586 read_cnt = tbl_rwc_test_param.count_keys_extbkt;
587 } else {
588 keys = tbl_rwc_test_param.keys_non_shift_path;
589 read_cnt = tbl_rwc_test_param.count_keys_non_shift_path;
590 }
591
592 extra_keys = read_cnt & (BULK_LOOKUP_SIZE - 1);
593
594 begin = rte_rdtsc_precise();
595 do {
596 if (read_type & BULK_LOOKUP) {
597 for (i = 0; i < (read_cnt - extra_keys);
598 i += BULK_LOOKUP_SIZE) {
599 /* Array of pointer to the list of keys */
600 for (j = 0; j < BULK_LOOKUP_SIZE; j++)
601 temp_a[j] = keys + i + j;
602 rte_hash_lookup_bulk(tbl_rwc_test_param.h,
603 (const void **)
604 ((uintptr_t)temp_a),
605 BULK_LOOKUP_SIZE, pos);
606 /* Validate lookup result */
607 for (j = 0; j < BULK_LOOKUP_SIZE; j++)
608 if ((read_type & READ_FAIL &&
609 pos[j] != -ENOENT) ||
610 (!(read_type & READ_FAIL) &&
611 pos[j] == -ENOENT)) {
612 printf("lookup failed!"
613 "%"PRIu32"\n",
614 keys[i + j]);
615 return -1;
616 }
617 }
618 for (j = 0; j < extra_keys; j++)
619 temp_a[j] = keys + i + j;
620
621 rte_hash_lookup_bulk(tbl_rwc_test_param.h,
622 (const void **)
623 ((uintptr_t)temp_a),
624 extra_keys, pos);
625 for (j = 0; j < extra_keys; j++)
626 if ((read_type & READ_FAIL &&
627 pos[j] != -ENOENT) ||
628 (!(read_type & READ_FAIL) &&
629 pos[j] == -ENOENT)) {
630 printf("lookup failed! %"PRIu32"\n",
631 keys[i + j]);
632 return -1;
633 }
634 } else {
635 for (i = 0; i < read_cnt; i++) {
636 ret = rte_hash_lookup
637 (tbl_rwc_test_param.h, keys + i);
638 if (((read_type & READ_FAIL) &&
639 (ret != -ENOENT)) ||
640 (!(read_type & READ_FAIL) &&
641 ret == -ENOENT)) {
642 printf("lookup failed! %"PRIu32"\n",
643 keys[i]);
644 return -1;
645 }
646 }
647 }
648 loop_cnt++;
649 } while (!writer_done);
650
651 cycles = rte_rdtsc_precise() - begin;
652 rte_atomic64_add(&gread_cycles, cycles);
653 rte_atomic64_add(&greads, read_cnt*loop_cnt);
654 return 0;
655 }
656
657 static int
658 write_keys(uint8_t write_type)
659 {
660 uint32_t i;
661 int ret;
662 uint32_t key_cnt = 0;
663 uint32_t *keys;
664 if (write_type == WRITE_KEY_SHIFT) {
665 key_cnt = tbl_rwc_test_param.count_keys_ks;
666 keys = tbl_rwc_test_param.keys_ks;
667 } else if (write_type == WRITE_NO_KEY_SHIFT) {
668 key_cnt = tbl_rwc_test_param.count_keys_no_ks;
669 keys = tbl_rwc_test_param.keys_no_ks;
670 } else if (write_type == WRITE_EXT_BKT) {
671 key_cnt = tbl_rwc_test_param.count_keys_extbkt;
672 keys = tbl_rwc_test_param.keys_ext_bkt;
673 }
674 for (i = 0; i < key_cnt; i++) {
675 ret = rte_hash_add_key(tbl_rwc_test_param.h, keys + i);
676 if ((write_type == WRITE_NO_KEY_SHIFT) && ret < 0) {
677 printf("writer failed %"PRIu32"\n", i);
678 return -1;
679 }
680 }
681 return 0;
682 }
683
684 static int
685 test_rwc_multi_writer(__attribute__((unused)) void *arg)
686 {
687 uint32_t i, offset;
688 uint32_t pos_core = (uint32_t)((uintptr_t)arg);
689 offset = pos_core * tbl_rwc_test_param.single_insert;
690 for (i = offset; i < offset + tbl_rwc_test_param.single_insert; i++)
691 rte_hash_add_key(tbl_rwc_test_param.h,
692 tbl_rwc_test_param.keys_ks + i);
693 multi_writer_done[pos_core] = 1;
694 return 0;
695 }
696
697 /*
698 * Test lookup perf:
699 * Reader(s) lookup keys present in the table.
700 */
701 static int
702 test_hash_add_no_ks_lookup_hit(struct rwc_perf *rwc_perf_results, int rwc_lf,
703 int htm, int ext_bkt)
704 {
705 unsigned int n, m;
706 uint64_t i;
707 int use_jhash = 0;
708 uint8_t write_type = WRITE_NO_KEY_SHIFT;
709 uint8_t read_type = READ_PASS_NO_KEY_SHIFTS;
710
711 rte_atomic64_init(&greads);
712 rte_atomic64_init(&gread_cycles);
713
714 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
715 goto err;
716 printf("\nTest: Hash add - no key-shifts, read - hit\n");
717 for (m = 0; m < 2; m++) {
718 if (m == 1) {
719 printf("\n** With bulk-lookup **\n");
720 read_type |= BULK_LOOKUP;
721 }
722 for (n = 0; n < NUM_TEST; n++) {
723 unsigned int tot_lcore = rte_lcore_count();
724 if (tot_lcore < rwc_core_cnt[n] + 1)
725 goto finish;
726
727 printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
728
729 rte_atomic64_clear(&greads);
730 rte_atomic64_clear(&gread_cycles);
731
732 rte_hash_reset(tbl_rwc_test_param.h);
733 writer_done = 0;
734 if (write_keys(write_type) < 0)
735 goto err;
736 writer_done = 1;
737 for (i = 1; i <= rwc_core_cnt[n]; i++)
738 rte_eal_remote_launch(test_rwc_reader,
739 (void *)(uintptr_t)read_type,
740 enabled_core_ids[i]);
741 rte_eal_mp_wait_lcore();
742
743 for (i = 1; i <= rwc_core_cnt[n]; i++)
744 if (lcore_config[i].ret < 0)
745 goto err;
746
747 unsigned long long cycles_per_lookup =
748 rte_atomic64_read(&gread_cycles) /
749 rte_atomic64_read(&greads);
750 rwc_perf_results->w_no_ks_r_hit[m][n]
751 = cycles_per_lookup;
752 printf("Cycles per lookup: %llu\n", cycles_per_lookup);
753 }
754 }
755
756 finish:
757 rte_hash_free(tbl_rwc_test_param.h);
758 return 0;
759
760 err:
761 rte_hash_free(tbl_rwc_test_param.h);
762 return -1;
763 }
764
765 /*
766 * Test lookup perf:
767 * Reader(s) lookup keys absent in the table while
768 * 'Main' thread adds with no key-shifts.
769 */
770 static int
771 test_hash_add_no_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf,
772 int htm, int ext_bkt)
773 {
774 unsigned int n, m;
775 uint64_t i;
776 int use_jhash = 0;
777 uint8_t write_type = WRITE_NO_KEY_SHIFT;
778 uint8_t read_type = READ_FAIL;
779 int ret;
780
781 rte_atomic64_init(&greads);
782 rte_atomic64_init(&gread_cycles);
783
784 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
785 goto err;
786 printf("\nTest: Hash add - no key-shifts, Hash lookup - miss\n");
787 for (m = 0; m < 2; m++) {
788 if (m == 1) {
789 printf("\n** With bulk-lookup **\n");
790 read_type |= BULK_LOOKUP;
791 }
792 for (n = 0; n < NUM_TEST; n++) {
793 unsigned int tot_lcore = rte_lcore_count();
794 if (tot_lcore < rwc_core_cnt[n] + 1)
795 goto finish;
796
797 printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
798
799 rte_atomic64_clear(&greads);
800 rte_atomic64_clear(&gread_cycles);
801
802 rte_hash_reset(tbl_rwc_test_param.h);
803 writer_done = 0;
804
805 for (i = 1; i <= rwc_core_cnt[n]; i++)
806 rte_eal_remote_launch(test_rwc_reader,
807 (void *)(uintptr_t)read_type,
808 enabled_core_ids[i]);
809 ret = write_keys(write_type);
810 writer_done = 1;
811 rte_eal_mp_wait_lcore();
812
813 if (ret < 0)
814 goto err;
815 for (i = 1; i <= rwc_core_cnt[n]; i++)
816 if (lcore_config[i].ret < 0)
817 goto err;
818
819 unsigned long long cycles_per_lookup =
820 rte_atomic64_read(&gread_cycles) /
821 rte_atomic64_read(&greads);
822 rwc_perf_results->w_no_ks_r_miss[m][n]
823 = cycles_per_lookup;
824 printf("Cycles per lookup: %llu\n", cycles_per_lookup);
825 }
826 }
827
828 finish:
829 rte_hash_free(tbl_rwc_test_param.h);
830 return 0;
831
832 err:
833 rte_hash_free(tbl_rwc_test_param.h);
834 return -1;
835 }
836
837 /*
838 * Test lookup perf:
839 * Reader(s) lookup keys present in the table and not likely to be on the
840 * shift path while 'Main' thread adds keys causing key-shifts.
841 */
842 static int
843 test_hash_add_ks_lookup_hit_non_sp(struct rwc_perf *rwc_perf_results,
844 int rwc_lf, int htm, int ext_bkt)
845 {
846 unsigned int n, m;
847 uint64_t i;
848 int use_jhash = 0;
849 int ret;
850 uint8_t write_type;
851 uint8_t read_type = READ_PASS_NON_SHIFT_PATH;
852
853 rte_atomic64_init(&greads);
854 rte_atomic64_init(&gread_cycles);
855
856 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
857 goto err;
858 printf("\nTest: Hash add - key shift, Hash lookup - hit"
859 " (non-shift-path)\n");
860 for (m = 0; m < 2; m++) {
861 if (m == 1) {
862 printf("\n** With bulk-lookup **\n");
863 read_type |= BULK_LOOKUP;
864 }
865 for (n = 0; n < NUM_TEST; n++) {
866 unsigned int tot_lcore = rte_lcore_count();
867 if (tot_lcore < rwc_core_cnt[n] + 1)
868 goto finish;
869
870 printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
871
872 rte_atomic64_clear(&greads);
873 rte_atomic64_clear(&gread_cycles);
874
875 rte_hash_reset(tbl_rwc_test_param.h);
876 writer_done = 0;
877 write_type = WRITE_NO_KEY_SHIFT;
878 if (write_keys(write_type) < 0)
879 goto err;
880 for (i = 1; i <= rwc_core_cnt[n]; i++)
881 rte_eal_remote_launch(test_rwc_reader,
882 (void *)(uintptr_t)read_type,
883 enabled_core_ids[i]);
884 write_type = WRITE_KEY_SHIFT;
885 ret = write_keys(write_type);
886 writer_done = 1;
887 rte_eal_mp_wait_lcore();
888
889 if (ret < 0)
890 goto err;
891 for (i = 1; i <= rwc_core_cnt[n]; i++)
892 if (lcore_config[i].ret < 0)
893 goto err;
894
895 unsigned long long cycles_per_lookup =
896 rte_atomic64_read(&gread_cycles) /
897 rte_atomic64_read(&greads);
898 rwc_perf_results->w_ks_r_hit_nsp[m][n]
899 = cycles_per_lookup;
900 printf("Cycles per lookup: %llu\n", cycles_per_lookup);
901 }
902 }
903
904 finish:
905 rte_hash_free(tbl_rwc_test_param.h);
906 return 0;
907
908 err:
909 rte_hash_free(tbl_rwc_test_param.h);
910 return -1;
911 }
912
913 /*
914 * Test lookup perf:
915 * Reader(s) lookup keys present in the table and likely on the shift-path while
916 * 'Main' thread adds keys causing key-shifts.
917 */
918 static int
919 test_hash_add_ks_lookup_hit_sp(struct rwc_perf *rwc_perf_results, int rwc_lf,
920 int htm, int ext_bkt)
921 {
922 unsigned int n, m;
923 uint64_t i;
924 int use_jhash = 0;
925 int ret;
926 uint8_t write_type;
927 uint8_t read_type = READ_PASS_SHIFT_PATH;
928
929 rte_atomic64_init(&greads);
930 rte_atomic64_init(&gread_cycles);
931
932 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
933 goto err;
934 printf("\nTest: Hash add - key shift, Hash lookup - hit (shift-path)"
935 "\n");
936
937 for (m = 0; m < 2; m++) {
938 if (m == 1) {
939 printf("\n** With bulk-lookup **\n");
940 read_type |= BULK_LOOKUP;
941 }
942 for (n = 0; n < NUM_TEST; n++) {
943 unsigned int tot_lcore = rte_lcore_count();
944 if (tot_lcore < rwc_core_cnt[n])
945 goto finish;
946
947 printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
948 rte_atomic64_clear(&greads);
949 rte_atomic64_clear(&gread_cycles);
950
951 rte_hash_reset(tbl_rwc_test_param.h);
952 writer_done = 0;
953 write_type = WRITE_NO_KEY_SHIFT;
954 if (write_keys(write_type) < 0)
955 goto err;
956 for (i = 1; i <= rwc_core_cnt[n]; i++)
957 rte_eal_remote_launch(test_rwc_reader,
958 (void *)(uintptr_t)read_type,
959 enabled_core_ids[i]);
960 write_type = WRITE_KEY_SHIFT;
961 ret = write_keys(write_type);
962 writer_done = 1;
963 rte_eal_mp_wait_lcore();
964
965 if (ret < 0)
966 goto err;
967 for (i = 1; i <= rwc_core_cnt[n]; i++)
968 if (lcore_config[i].ret < 0)
969 goto err;
970
971 unsigned long long cycles_per_lookup =
972 rte_atomic64_read(&gread_cycles) /
973 rte_atomic64_read(&greads);
974 rwc_perf_results->w_ks_r_hit_sp[m][n]
975 = cycles_per_lookup;
976 printf("Cycles per lookup: %llu\n", cycles_per_lookup);
977 }
978 }
979
980 finish:
981 rte_hash_free(tbl_rwc_test_param.h);
982 return 0;
983
984 err:
985 rte_hash_free(tbl_rwc_test_param.h);
986 return -1;
987 }
988
989 /*
990 * Test lookup perf:
991 * Reader(s) lookup keys absent in the table while
992 * 'Main' thread adds keys causing key-shifts.
993 */
994 static int
995 test_hash_add_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf, int
996 htm, int ext_bkt)
997 {
998 unsigned int n, m;
999 uint64_t i;
1000 int use_jhash = 0;
1001 int ret;
1002 uint8_t write_type;
1003 uint8_t read_type = READ_FAIL;
1004
1005 rte_atomic64_init(&greads);
1006 rte_atomic64_init(&gread_cycles);
1007
1008 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
1009 goto err;
1010 printf("\nTest: Hash add - key shift, Hash lookup - miss\n");
1011 for (m = 0; m < 2; m++) {
1012 if (m == 1) {
1013 printf("\n** With bulk-lookup **\n");
1014 read_type |= BULK_LOOKUP;
1015 }
1016 for (n = 0; n < NUM_TEST; n++) {
1017 unsigned int tot_lcore = rte_lcore_count();
1018 if (tot_lcore < rwc_core_cnt[n] + 1)
1019 goto finish;
1020
1021 printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
1022
1023 rte_atomic64_clear(&greads);
1024 rte_atomic64_clear(&gread_cycles);
1025
1026 rte_hash_reset(tbl_rwc_test_param.h);
1027 writer_done = 0;
1028 write_type = WRITE_NO_KEY_SHIFT;
1029 if (write_keys(write_type) < 0)
1030 goto err;
1031 for (i = 1; i <= rwc_core_cnt[n]; i++)
1032 rte_eal_remote_launch(test_rwc_reader,
1033 (void *)(uintptr_t)read_type,
1034 enabled_core_ids[i]);
1035 write_type = WRITE_KEY_SHIFT;
1036 ret = write_keys(write_type);
1037 writer_done = 1;
1038 rte_eal_mp_wait_lcore();
1039
1040 if (ret < 0)
1041 goto err;
1042 for (i = 1; i <= rwc_core_cnt[n]; i++)
1043 if (lcore_config[i].ret < 0)
1044 goto err;
1045
1046 unsigned long long cycles_per_lookup =
1047 rte_atomic64_read(&gread_cycles) /
1048 rte_atomic64_read(&greads);
1049 rwc_perf_results->w_ks_r_miss[m][n] = cycles_per_lookup;
1050 printf("Cycles per lookup: %llu\n", cycles_per_lookup);
1051 }
1052 }
1053
1054 finish:
1055 rte_hash_free(tbl_rwc_test_param.h);
1056 return 0;
1057
1058 err:
1059 rte_hash_free(tbl_rwc_test_param.h);
1060 return -1;
1061 }
1062
1063 /*
1064 * Test lookup perf for multi-writer:
1065 * Reader(s) lookup keys present in the table and likely on the shift-path while
1066 * Writers add keys causing key-shiftsi.
1067 * Writers are running in parallel, on different data plane cores.
1068 */
1069 static int
1070 test_hash_multi_add_lookup(struct rwc_perf *rwc_perf_results, int rwc_lf,
1071 int htm, int ext_bkt)
1072 {
1073 unsigned int n, m, k;
1074 uint64_t i;
1075 int use_jhash = 0;
1076 uint8_t write_type;
1077 uint8_t read_type = READ_PASS_SHIFT_PATH;
1078
1079 rte_atomic64_init(&greads);
1080 rte_atomic64_init(&gread_cycles);
1081
1082 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
1083 goto err;
1084 printf("\nTest: Multi-add-lookup\n");
1085 uint8_t pos_core;
1086 for (m = 1; m < NUM_TEST; m++) {
1087 /* Calculate keys added by each writer */
1088 tbl_rwc_test_param.single_insert =
1089 tbl_rwc_test_param.count_keys_ks / rwc_core_cnt[m];
1090 for (k = 0; k < 2; k++) {
1091 if (k == 1) {
1092 printf("\n** With bulk-lookup **\n");
1093 read_type |= BULK_LOOKUP;
1094 }
1095 for (n = 0; n < NUM_TEST; n++) {
1096 unsigned int tot_lcore = rte_lcore_count();
1097 if (tot_lcore < (rwc_core_cnt[n] +
1098 rwc_core_cnt[m] + 1))
1099 goto finish;
1100
1101 printf("\nNumber of writers: %u",
1102 rwc_core_cnt[m]);
1103 printf("\nNumber of readers: %u\n",
1104 rwc_core_cnt[n]);
1105
1106 rte_atomic64_clear(&greads);
1107 rte_atomic64_clear(&gread_cycles);
1108
1109 rte_hash_reset(tbl_rwc_test_param.h);
1110 writer_done = 0;
1111 for (i = 0; i < 4; i++)
1112 multi_writer_done[i] = 0;
1113 write_type = WRITE_NO_KEY_SHIFT;
1114 if (write_keys(write_type) < 0)
1115 goto err;
1116
1117 /* Launch reader(s) */
1118 for (i = 1; i <= rwc_core_cnt[n]; i++)
1119 rte_eal_remote_launch(test_rwc_reader,
1120 (void *)(uintptr_t)read_type,
1121 enabled_core_ids[i]);
1122 write_type = WRITE_KEY_SHIFT;
1123 pos_core = 0;
1124
1125 /* Launch writers */
1126 for (; i <= rwc_core_cnt[m]
1127 + rwc_core_cnt[n]; i++) {
1128 rte_eal_remote_launch
1129 (test_rwc_multi_writer,
1130 (void *)(uintptr_t)pos_core,
1131 enabled_core_ids[i]);
1132 pos_core++;
1133 }
1134
1135 /* Wait for writers to complete */
1136 for (i = 0; i < rwc_core_cnt[m]; i++)
1137 while
1138 (multi_writer_done[i] == 0);
1139 writer_done = 1;
1140
1141 rte_eal_mp_wait_lcore();
1142
1143 for (i = 1; i <= rwc_core_cnt[n]; i++)
1144 if (lcore_config[i].ret < 0)
1145 goto err;
1146
1147 unsigned long long cycles_per_lookup =
1148 rte_atomic64_read(&gread_cycles)
1149 / rte_atomic64_read(&greads);
1150 rwc_perf_results->multi_rw[m][k][n]
1151 = cycles_per_lookup;
1152 printf("Cycles per lookup: %llu\n",
1153 cycles_per_lookup);
1154 }
1155 }
1156 }
1157
1158 finish:
1159 rte_hash_free(tbl_rwc_test_param.h);
1160 return 0;
1161
1162 err:
1163 rte_hash_free(tbl_rwc_test_param.h);
1164 return -1;
1165 }
1166
1167 /*
1168 * Test lookup perf:
1169 * Reader(s) lookup keys present in the extendable bkt.
1170 */
1171 static int
1172 test_hash_add_ks_lookup_hit_extbkt(struct rwc_perf *rwc_perf_results,
1173 int rwc_lf, int htm, int ext_bkt)
1174 {
1175 unsigned int n, m;
1176 uint64_t i;
1177 int use_jhash = 0;
1178 uint8_t write_type;
1179 uint8_t read_type = READ_PASS_KEY_SHIFTS_EXTBKT;
1180
1181 rte_atomic64_init(&greads);
1182 rte_atomic64_init(&gread_cycles);
1183
1184 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
1185 goto err;
1186 printf("\nTest: Hash add - key-shifts, read - hit (ext_bkt)\n");
1187 for (m = 0; m < 2; m++) {
1188 if (m == 1) {
1189 printf("\n** With bulk-lookup **\n");
1190 read_type |= BULK_LOOKUP;
1191 }
1192 for (n = 0; n < NUM_TEST; n++) {
1193 unsigned int tot_lcore = rte_lcore_count();
1194 if (tot_lcore < rwc_core_cnt[n] + 1)
1195 goto finish;
1196
1197 printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
1198
1199 rte_atomic64_clear(&greads);
1200 rte_atomic64_clear(&gread_cycles);
1201
1202 rte_hash_reset(tbl_rwc_test_param.h);
1203 write_type = WRITE_NO_KEY_SHIFT;
1204 if (write_keys(write_type) < 0)
1205 goto err;
1206 write_type = WRITE_KEY_SHIFT;
1207 if (write_keys(write_type) < 0)
1208 goto err;
1209 writer_done = 0;
1210 for (i = 1; i <= rwc_core_cnt[n]; i++)
1211 rte_eal_remote_launch(test_rwc_reader,
1212 (void *)(uintptr_t)read_type,
1213 enabled_core_ids[i]);
1214 for (i = 0; i < tbl_rwc_test_param.count_keys_ks_extbkt;
1215 i++) {
1216 if (rte_hash_del_key(tbl_rwc_test_param.h,
1217 tbl_rwc_test_param.keys_ks_extbkt + i)
1218 < 0) {
1219 printf("Delete Failed: %u\n",
1220 tbl_rwc_test_param.keys_ks_extbkt[i]);
1221 goto err;
1222 }
1223 }
1224 writer_done = 1;
1225 rte_eal_mp_wait_lcore();
1226
1227 for (i = 1; i <= rwc_core_cnt[n]; i++)
1228 if (lcore_config[i].ret < 0)
1229 goto err;
1230
1231 unsigned long long cycles_per_lookup =
1232 rte_atomic64_read(&gread_cycles) /
1233 rte_atomic64_read(&greads);
1234 rwc_perf_results->w_ks_r_hit_extbkt[m][n]
1235 = cycles_per_lookup;
1236 printf("Cycles per lookup: %llu\n", cycles_per_lookup);
1237 }
1238 }
1239
1240 finish:
1241 rte_hash_free(tbl_rwc_test_param.h);
1242 return 0;
1243
1244 err:
1245 rte_hash_free(tbl_rwc_test_param.h);
1246 return -1;
1247 }
1248
1249 static int
1250 test_hash_readwrite_lf_main(void)
1251 {
1252 /*
1253 * Variables used to choose different tests.
1254 * rwc_lf indicates if read-write concurrency lock-free support is
1255 * enabled.
1256 * htm indicates if Hardware transactional memory support is enabled.
1257 */
1258 int rwc_lf = 0;
1259 int htm;
1260 int use_jhash = 0;
1261 int ext_bkt = 0;
1262 if (rte_lcore_count() == 1) {
1263 printf("More than one lcore is required "
1264 "to do read write lock-free concurrency test\n");
1265 return -1;
1266 }
1267
1268 setlocale(LC_NUMERIC, "");
1269
1270 if (rte_tm_supported())
1271 htm = 1;
1272 else
1273 htm = 0;
1274
1275 if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
1276 return -1;
1277 if (generate_keys() != 0)
1278 return -1;
1279 if (get_enabled_cores_list() != 0)
1280 return -1;
1281
1282 if (RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF) {
1283 rwc_lf = 1;
1284 ext_bkt = 1;
1285 printf("Test lookup with read-write concurrency lock free support"
1286 " enabled\n");
1287 if (test_hash_add_no_ks_lookup_hit(&rwc_lf_results, rwc_lf,
1288 htm, ext_bkt) < 0)
1289 return -1;
1290 if (test_hash_add_no_ks_lookup_miss(&rwc_lf_results, rwc_lf,
1291 htm, ext_bkt) < 0)
1292 return -1;
1293 if (test_hash_add_ks_lookup_hit_non_sp(&rwc_lf_results, rwc_lf,
1294 htm, ext_bkt) < 0)
1295 return -1;
1296 if (test_hash_add_ks_lookup_hit_sp(&rwc_lf_results, rwc_lf,
1297 htm, ext_bkt) < 0)
1298 return -1;
1299 if (test_hash_add_ks_lookup_miss(&rwc_lf_results, rwc_lf, htm,
1300 ext_bkt) < 0)
1301 return -1;
1302 if (test_hash_multi_add_lookup(&rwc_lf_results, rwc_lf, htm,
1303 ext_bkt) < 0)
1304 return -1;
1305 if (test_hash_add_ks_lookup_hit_extbkt(&rwc_lf_results, rwc_lf,
1306 htm, ext_bkt) < 0)
1307 return -1;
1308 }
1309 printf("\nTest lookup with read-write concurrency lock free support"
1310 " disabled\n");
1311 rwc_lf = 0;
1312 if (!htm) {
1313 printf("With HTM Disabled\n");
1314 if (!RUN_WITH_HTM_DISABLED) {
1315 printf("Enable RUN_WITH_HTM_DISABLED to test with"
1316 " lock-free disabled");
1317 goto results;
1318 }
1319 } else
1320 printf("With HTM Enabled\n");
1321 if (test_hash_add_no_ks_lookup_hit(&rwc_non_lf_results, rwc_lf, htm,
1322 ext_bkt) < 0)
1323 return -1;
1324 if (test_hash_add_no_ks_lookup_miss(&rwc_non_lf_results, rwc_lf, htm,
1325 ext_bkt) < 0)
1326 return -1;
1327 if (test_hash_add_ks_lookup_hit_non_sp(&rwc_non_lf_results, rwc_lf,
1328 htm, ext_bkt) < 0)
1329 return -1;
1330 if (test_hash_add_ks_lookup_hit_sp(&rwc_non_lf_results, rwc_lf, htm,
1331 ext_bkt) < 0)
1332 return -1;
1333 if (test_hash_add_ks_lookup_miss(&rwc_non_lf_results, rwc_lf, htm,
1334 ext_bkt) < 0)
1335 return -1;
1336 if (test_hash_multi_add_lookup(&rwc_non_lf_results, rwc_lf, htm,
1337 ext_bkt) < 0)
1338 return -1;
1339 if (test_hash_add_ks_lookup_hit_extbkt(&rwc_non_lf_results, rwc_lf,
1340 htm, ext_bkt) < 0)
1341 return -1;
1342 results:
1343 printf("\n\t\t\t\t\t\t********** Results summary **********\n\n");
1344 int i, j, k;
1345 for (j = 0; j < 2; j++) {
1346 if (j == 1)
1347 printf("\n\t\t\t\t\t#######********** Bulk Lookup "
1348 "**********#######\n\n");
1349 printf("_______\t\t_______\t\t_________\t___\t\t_________\t\t"
1350 "\t\t\t\t_________________\n");
1351 printf("Writers\t\tReaders\t\tLock-free\tHTM\t\tTest-case\t\t\t"
1352 "\t\t\tCycles per lookup\n");
1353 printf("_______\t\t_______\t\t_________\t___\t\t_________\t\t\t"
1354 "\t\t\t_________________\n");
1355 for (i = 0; i < NUM_TEST; i++) {
1356 printf("%u\t\t%u\t\t", 1, rwc_core_cnt[i]);
1357 printf("Enabled\t\t");
1358 printf("N/A\t\t");
1359 printf("Hash add - no key-shifts, lookup - hit\t\t\t\t"
1360 "%u\n\t\t\t\t\t\t\t\t",
1361 rwc_lf_results.w_no_ks_r_hit[j][i]);
1362 printf("Hash add - no key-shifts, lookup - miss\t\t\t\t"
1363 "%u\n\t\t\t\t\t\t\t\t",
1364 rwc_lf_results.w_no_ks_r_miss[j][i]);
1365 printf("Hash add - key-shifts, lookup - hit"
1366 "(non-shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
1367 rwc_lf_results.w_ks_r_hit_nsp[j][i]);
1368 printf("Hash add - key-shifts, lookup - hit "
1369 "(shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
1370 rwc_lf_results.w_ks_r_hit_sp[j][i]);
1371 printf("Hash add - key-shifts, Hash lookup miss\t\t\t\t"
1372 "%u\n\t\t\t\t\t\t\t\t",
1373 rwc_lf_results.w_ks_r_miss[j][i]);
1374 printf("Hash add - key-shifts, Hash lookup hit (ext_bkt)\t\t"
1375 "%u\n\n\t\t\t\t",
1376 rwc_lf_results.w_ks_r_hit_extbkt[j][i]);
1377
1378 printf("Disabled\t");
1379 if (htm)
1380 printf("Enabled\t\t");
1381 else
1382 printf("Disabled\t");
1383 printf("Hash add - no key-shifts, lookup - hit\t\t\t\t"
1384 "%u\n\t\t\t\t\t\t\t\t",
1385 rwc_non_lf_results.w_no_ks_r_hit[j][i]);
1386 printf("Hash add - no key-shifts, lookup - miss\t\t\t\t"
1387 "%u\n\t\t\t\t\t\t\t\t",
1388 rwc_non_lf_results.w_no_ks_r_miss[j][i]);
1389 printf("Hash add - key-shifts, lookup - hit "
1390 "(non-shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
1391 rwc_non_lf_results.w_ks_r_hit_nsp[j][i]);
1392 printf("Hash add - key-shifts, lookup - hit "
1393 "(shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
1394 rwc_non_lf_results.w_ks_r_hit_sp[j][i]);
1395 printf("Hash add - key-shifts, Hash lookup miss\t\t\t\t"
1396 "%u\n\t\t\t\t\t\t\t\t",
1397 rwc_non_lf_results.w_ks_r_miss[j][i]);
1398 printf("Hash add - key-shifts, Hash lookup hit (ext_bkt)\t\t"
1399 "%u\n",
1400 rwc_non_lf_results.w_ks_r_hit_extbkt[j][i]);
1401
1402 printf("_______\t\t_______\t\t_________\t___\t\t"
1403 "_________\t\t\t\t\t\t_________________\n");
1404 }
1405
1406 for (i = 1; i < NUM_TEST; i++) {
1407 for (k = 0; k < NUM_TEST; k++) {
1408 printf("%u", rwc_core_cnt[i]);
1409 printf("\t\t%u\t\t", rwc_core_cnt[k]);
1410 printf("Enabled\t\t");
1411 printf("N/A\t\t");
1412 printf("Multi-add-lookup\t\t\t\t\t\t%u\n\n\t\t"
1413 "\t\t",
1414 rwc_lf_results.multi_rw[i][j][k]);
1415 printf("Disabled\t");
1416 if (htm)
1417 printf("Enabled\t\t");
1418 else
1419 printf("Disabled\t");
1420 printf("Multi-add-lookup\t\t\t\t\t\t%u\n",
1421 rwc_non_lf_results.multi_rw[i][j][k]);
1422
1423 printf("_______\t\t_______\t\t_________\t___"
1424 "\t\t_________\t\t\t\t\t\t"
1425 "_________________\n");
1426 }
1427 }
1428 }
1429 rte_free(tbl_rwc_test_param.keys);
1430 rte_free(tbl_rwc_test_param.keys_no_ks);
1431 rte_free(tbl_rwc_test_param.keys_ks);
1432 rte_free(tbl_rwc_test_param.keys_absent);
1433 rte_free(tbl_rwc_test_param.keys_shift_path);
1434 rte_free(scanned_bkts);
1435 return 0;
1436 }
1437
1438 REGISTER_TEST_COMMAND(hash_readwrite_lf_autotest, test_hash_readwrite_lf_main);