xref: /dpdk/app/test/test_hash_readwrite.c (revision b6a7e6852e9ab82ae0e05e2d2a0b83abca17de3b)
1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson  * Copyright(c) 2018 Intel Corporation
3a9de470cSBruce Richardson  */
4a9de470cSBruce Richardson 
5a9de470cSBruce Richardson #include <inttypes.h>
6a9de470cSBruce Richardson #include <locale.h>
7a9de470cSBruce Richardson 
8a9de470cSBruce Richardson #include <rte_cycles.h>
9a9de470cSBruce Richardson #include <rte_hash.h>
10a9de470cSBruce Richardson #include <rte_hash_crc.h>
11a9de470cSBruce Richardson #include <rte_jhash.h>
12a9de470cSBruce Richardson #include <rte_launch.h>
13a9de470cSBruce Richardson #include <rte_malloc.h>
14a9de470cSBruce Richardson #include <rte_random.h>
15a9de470cSBruce Richardson #include <rte_spinlock.h>
16a9de470cSBruce Richardson 
17a9de470cSBruce Richardson #include "test.h"
18a9de470cSBruce Richardson 
19a9de470cSBruce Richardson #define RTE_RWTEST_FAIL 0
20a9de470cSBruce Richardson 
21a9de470cSBruce Richardson #define TOTAL_ENTRY (5*1024*1024)
22a9de470cSBruce Richardson #define TOTAL_INSERT (4.5*1024*1024)
23a9de470cSBruce Richardson #define TOTAL_INSERT_EXT (5*1024*1024)
24a9de470cSBruce Richardson 
25a9de470cSBruce Richardson #define NUM_TEST 3
26a9de470cSBruce Richardson unsigned int core_cnt[NUM_TEST] = {2, 4, 8};
27a9de470cSBruce Richardson 
28cb056611SStephen Hemminger unsigned int worker_core_ids[RTE_MAX_LCORE];
29a9de470cSBruce Richardson struct perf {
30a9de470cSBruce Richardson 	uint32_t single_read;
31a9de470cSBruce Richardson 	uint32_t single_write;
32a9de470cSBruce Richardson 	uint32_t read_only[NUM_TEST];
33a9de470cSBruce Richardson 	uint32_t write_only[NUM_TEST];
34a9de470cSBruce Richardson 	uint32_t read_write_r[NUM_TEST];
35a9de470cSBruce Richardson 	uint32_t read_write_w[NUM_TEST];
36a9de470cSBruce Richardson };
37a9de470cSBruce Richardson 
38a9de470cSBruce Richardson static struct perf htm_results, non_htm_results;
39a9de470cSBruce Richardson 
40a9de470cSBruce Richardson struct {
41a9de470cSBruce Richardson 	uint32_t *keys;
42a9de470cSBruce Richardson 	uint8_t *found;
43a9de470cSBruce Richardson 	uint32_t num_insert;
44a9de470cSBruce Richardson 	uint32_t rounded_tot_insert;
45a9de470cSBruce Richardson 	struct rte_hash *h;
46a9de470cSBruce Richardson } tbl_rw_test_param;
47a9de470cSBruce Richardson 
48*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint64_t) gcycles;
49*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint64_t) ginsertions;
50a9de470cSBruce Richardson 
51*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint64_t) gread_cycles;
52*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint64_t) gwrite_cycles;
53a9de470cSBruce Richardson 
54*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint64_t) greads;
55*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint64_t) gwrites;
56a9de470cSBruce Richardson 
57a9de470cSBruce Richardson static int
test_hash_readwrite_worker(__rte_unused void * arg)58f2fc83b4SThomas Monjalon test_hash_readwrite_worker(__rte_unused void *arg)
59a9de470cSBruce Richardson {
60a9de470cSBruce Richardson 	uint64_t i, offset;
61a9de470cSBruce Richardson 	uint32_t lcore_id = rte_lcore_id();
62a9de470cSBruce Richardson 	uint64_t begin, cycles;
63a9de470cSBruce Richardson 	int *ret;
64a9de470cSBruce Richardson 
65a9de470cSBruce Richardson 	ret = rte_malloc(NULL, sizeof(int) *
66a9de470cSBruce Richardson 				tbl_rw_test_param.num_insert, 0);
67a9de470cSBruce Richardson 	for (i = 0; i < rte_lcore_count(); i++) {
68cb056611SStephen Hemminger 		if (worker_core_ids[i] == lcore_id)
69a9de470cSBruce Richardson 			break;
70a9de470cSBruce Richardson 	}
71a9de470cSBruce Richardson 	offset = tbl_rw_test_param.num_insert * i;
72a9de470cSBruce Richardson 
73a9de470cSBruce Richardson 	printf("Core #%d inserting and reading %d: %'"PRId64" - %'"PRId64"\n",
74a9de470cSBruce Richardson 	       lcore_id, tbl_rw_test_param.num_insert,
75a9de470cSBruce Richardson 	       offset, offset + tbl_rw_test_param.num_insert - 1);
76a9de470cSBruce Richardson 
77a9de470cSBruce Richardson 	begin = rte_rdtsc_precise();
78a9de470cSBruce Richardson 
79a9de470cSBruce Richardson 	for (i = offset; i < offset + tbl_rw_test_param.num_insert; i++) {
80a9de470cSBruce Richardson 
81a9de470cSBruce Richardson 		if (rte_hash_lookup(tbl_rw_test_param.h,
82a9de470cSBruce Richardson 				tbl_rw_test_param.keys + i) > 0)
83a9de470cSBruce Richardson 			break;
84a9de470cSBruce Richardson 
85a9de470cSBruce Richardson 		ret[i - offset] = rte_hash_add_key(tbl_rw_test_param.h,
86a9de470cSBruce Richardson 				     tbl_rw_test_param.keys + i);
87a9de470cSBruce Richardson 		if (ret[i - offset] < 0)
88a9de470cSBruce Richardson 			break;
89a9de470cSBruce Richardson 
90a9de470cSBruce Richardson 		/* lookup a random key */
91a9de470cSBruce Richardson 		uint32_t rand = rte_rand() % (i + 1 - offset);
92a9de470cSBruce Richardson 
93a9de470cSBruce Richardson 		if (rte_hash_lookup(tbl_rw_test_param.h,
94a9de470cSBruce Richardson 				tbl_rw_test_param.keys + rand) != ret[rand])
95a9de470cSBruce Richardson 			break;
96a9de470cSBruce Richardson 
97a9de470cSBruce Richardson 
98a9de470cSBruce Richardson 		if (rte_hash_del_key(tbl_rw_test_param.h,
99a9de470cSBruce Richardson 				tbl_rw_test_param.keys + rand) != ret[rand])
100a9de470cSBruce Richardson 			break;
101a9de470cSBruce Richardson 
102a9de470cSBruce Richardson 		ret[rand] = rte_hash_add_key(tbl_rw_test_param.h,
103a9de470cSBruce Richardson 					tbl_rw_test_param.keys + rand);
104a9de470cSBruce Richardson 		if (ret[rand] < 0)
105a9de470cSBruce Richardson 			break;
106a9de470cSBruce Richardson 
107a9de470cSBruce Richardson 		if (rte_hash_lookup(tbl_rw_test_param.h,
108a9de470cSBruce Richardson 			tbl_rw_test_param.keys + rand) != ret[rand])
109a9de470cSBruce Richardson 			break;
110a9de470cSBruce Richardson 	}
111a9de470cSBruce Richardson 
112a9de470cSBruce Richardson 	cycles = rte_rdtsc_precise() - begin;
113*b6a7e685STyler Retzlaff 	rte_atomic_fetch_add_explicit(&gcycles, cycles, rte_memory_order_relaxed);
114*b6a7e685STyler Retzlaff 	rte_atomic_fetch_add_explicit(&ginsertions, i - offset, rte_memory_order_relaxed);
115a9de470cSBruce Richardson 
116a9de470cSBruce Richardson 	for (; i < offset + tbl_rw_test_param.num_insert; i++)
117a9de470cSBruce Richardson 		tbl_rw_test_param.keys[i] = RTE_RWTEST_FAIL;
118a9de470cSBruce Richardson 
119a9de470cSBruce Richardson 	rte_free(ret);
120a9de470cSBruce Richardson 	return 0;
121a9de470cSBruce Richardson }
122a9de470cSBruce Richardson 
123a9de470cSBruce Richardson static int
init_params(int use_ext,int use_htm,int rw_lf,int use_jhash)12403a0ed1aSHonnappa Nagarahalli init_params(int use_ext, int use_htm, int rw_lf, int use_jhash)
125a9de470cSBruce Richardson {
126a9de470cSBruce Richardson 	unsigned int i;
127a9de470cSBruce Richardson 
128a9de470cSBruce Richardson 	uint32_t *keys = NULL;
129a9de470cSBruce Richardson 	uint8_t *found = NULL;
130a9de470cSBruce Richardson 	struct rte_hash *handle;
131a9de470cSBruce Richardson 
132a9de470cSBruce Richardson 	struct rte_hash_parameters hash_params = {
133a9de470cSBruce Richardson 		.entries = TOTAL_ENTRY,
134a9de470cSBruce Richardson 		.key_len = sizeof(uint32_t),
135a9de470cSBruce Richardson 		.hash_func_init_val = 0,
136a9de470cSBruce Richardson 		.socket_id = rte_socket_id(),
137a9de470cSBruce Richardson 	};
138a9de470cSBruce Richardson 	if (use_jhash)
139a9de470cSBruce Richardson 		hash_params.hash_func = rte_jhash;
140a9de470cSBruce Richardson 	else
141a9de470cSBruce Richardson 		hash_params.hash_func = rte_hash_crc;
142a9de470cSBruce Richardson 
14303a0ed1aSHonnappa Nagarahalli 	hash_params.extra_flag = RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
144a9de470cSBruce Richardson 	if (use_htm)
14503a0ed1aSHonnappa Nagarahalli 		hash_params.extra_flag |=
14603a0ed1aSHonnappa Nagarahalli 			RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT;
14703a0ed1aSHonnappa Nagarahalli 	if (rw_lf)
14803a0ed1aSHonnappa Nagarahalli 		hash_params.extra_flag |=
14903a0ed1aSHonnappa Nagarahalli 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
150a9de470cSBruce Richardson 	else
15103a0ed1aSHonnappa Nagarahalli 		hash_params.extra_flag |=
15203a0ed1aSHonnappa Nagarahalli 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY;
153a9de470cSBruce Richardson 
154a9de470cSBruce Richardson 	if (use_ext)
155a9de470cSBruce Richardson 		hash_params.extra_flag |=
156a9de470cSBruce Richardson 			RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
157a9de470cSBruce Richardson 	else
158a9de470cSBruce Richardson 		hash_params.extra_flag &=
159a9de470cSBruce Richardson 		       ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
160a9de470cSBruce Richardson 
161a9de470cSBruce Richardson 	hash_params.name = "tests";
162a9de470cSBruce Richardson 
163a9de470cSBruce Richardson 	handle = rte_hash_create(&hash_params);
164a9de470cSBruce Richardson 	if (handle == NULL) {
1651afb336dSMin Zhou 		printf("hash creation failed\n");
166a9de470cSBruce Richardson 		return -1;
167a9de470cSBruce Richardson 	}
168a9de470cSBruce Richardson 
169a9de470cSBruce Richardson 	tbl_rw_test_param.h = handle;
170a9de470cSBruce Richardson 	keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_ENTRY, 0);
171a9de470cSBruce Richardson 
172a9de470cSBruce Richardson 	if (keys == NULL) {
173a9de470cSBruce Richardson 		printf("RTE_MALLOC failed\n");
174a9de470cSBruce Richardson 		goto err;
175a9de470cSBruce Richardson 	}
176a9de470cSBruce Richardson 
177a9de470cSBruce Richardson 	found = rte_zmalloc(NULL, sizeof(uint8_t) * TOTAL_ENTRY, 0);
178a9de470cSBruce Richardson 	if (found == NULL) {
179a9de470cSBruce Richardson 		printf("RTE_ZMALLOC failed\n");
180a9de470cSBruce Richardson 		goto err;
181a9de470cSBruce Richardson 	}
182a9de470cSBruce Richardson 
183a9de470cSBruce Richardson 	tbl_rw_test_param.keys = keys;
184a9de470cSBruce Richardson 	tbl_rw_test_param.found = found;
185a9de470cSBruce Richardson 
186a9de470cSBruce Richardson 	for (i = 0; i < TOTAL_ENTRY; i++)
187a9de470cSBruce Richardson 		keys[i] = i;
188a9de470cSBruce Richardson 
189a9de470cSBruce Richardson 	return 0;
190a9de470cSBruce Richardson 
191a9de470cSBruce Richardson err:
192a9de470cSBruce Richardson 	rte_free(keys);
193a9de470cSBruce Richardson 	rte_hash_free(handle);
194a9de470cSBruce Richardson 
195a9de470cSBruce Richardson 	return -1;
196a9de470cSBruce Richardson }
197a9de470cSBruce Richardson 
198a9de470cSBruce Richardson static int
test_hash_readwrite_functional(int use_htm,int use_rw_lf,int use_ext)19903a0ed1aSHonnappa Nagarahalli test_hash_readwrite_functional(int use_htm, int use_rw_lf, int use_ext)
200a9de470cSBruce Richardson {
201a9de470cSBruce Richardson 	unsigned int i;
202a9de470cSBruce Richardson 	const void *next_key;
203a9de470cSBruce Richardson 	void *next_data;
204a9de470cSBruce Richardson 	uint32_t iter = 0;
205a9de470cSBruce Richardson 
206a9de470cSBruce Richardson 	uint32_t duplicated_keys = 0;
207a9de470cSBruce Richardson 	uint32_t lost_keys = 0;
208a9de470cSBruce Richardson 	int use_jhash = 1;
209cb056611SStephen Hemminger 	int worker_cnt = rte_lcore_count() - 1;
210a9de470cSBruce Richardson 	uint32_t tot_insert = 0;
211a9de470cSBruce Richardson 
212*b6a7e685STyler Retzlaff 	rte_atomic_store_explicit(&gcycles, 0, rte_memory_order_relaxed);
213*b6a7e685STyler Retzlaff 	rte_atomic_store_explicit(&ginsertions, 0, rte_memory_order_relaxed);
214a9de470cSBruce Richardson 
21503a0ed1aSHonnappa Nagarahalli 	if (init_params(use_ext, use_htm, use_rw_lf, use_jhash) != 0)
216a9de470cSBruce Richardson 		goto err;
217a9de470cSBruce Richardson 
218a9de470cSBruce Richardson 	if (use_ext)
219a9de470cSBruce Richardson 		tot_insert = TOTAL_INSERT_EXT;
220a9de470cSBruce Richardson 	else
221a9de470cSBruce Richardson 		tot_insert = TOTAL_INSERT;
222a9de470cSBruce Richardson 
223a9de470cSBruce Richardson 	tbl_rw_test_param.num_insert =
224cb056611SStephen Hemminger 		tot_insert / worker_cnt;
225a9de470cSBruce Richardson 
226a9de470cSBruce Richardson 	tbl_rw_test_param.rounded_tot_insert =
227cb056611SStephen Hemminger 		tbl_rw_test_param.num_insert * worker_cnt;
228a9de470cSBruce Richardson 
22903a0ed1aSHonnappa Nagarahalli 	printf("\nHTM = %d, RW-LF = %d, EXT-Table = %d\n",
23003a0ed1aSHonnappa Nagarahalli 		use_htm, use_rw_lf, use_ext);
231a9de470cSBruce Richardson 	printf("++++++++Start function tests:+++++++++\n");
232a9de470cSBruce Richardson 
233a9de470cSBruce Richardson 	/* Fire all threads. */
234a9de470cSBruce Richardson 	rte_eal_mp_remote_launch(test_hash_readwrite_worker,
235cb056611SStephen Hemminger 				 NULL, SKIP_MAIN);
236a9de470cSBruce Richardson 	rte_eal_mp_wait_lcore();
237a9de470cSBruce Richardson 
238a9de470cSBruce Richardson 	while (rte_hash_iterate(tbl_rw_test_param.h, &next_key,
239a9de470cSBruce Richardson 			&next_data, &iter) >= 0) {
240a9de470cSBruce Richardson 		/* Search for the key in the list of keys added .*/
241a9de470cSBruce Richardson 		i = *(const uint32_t *)next_key;
242a9de470cSBruce Richardson 		tbl_rw_test_param.found[i]++;
243a9de470cSBruce Richardson 	}
244a9de470cSBruce Richardson 
245a9de470cSBruce Richardson 	for (i = 0; i < tbl_rw_test_param.rounded_tot_insert; i++) {
246a9de470cSBruce Richardson 		if (tbl_rw_test_param.keys[i] != RTE_RWTEST_FAIL) {
247a9de470cSBruce Richardson 			if (tbl_rw_test_param.found[i] > 1) {
248a9de470cSBruce Richardson 				duplicated_keys++;
249a9de470cSBruce Richardson 				break;
250a9de470cSBruce Richardson 			}
251a9de470cSBruce Richardson 			if (tbl_rw_test_param.found[i] == 0) {
252a9de470cSBruce Richardson 				lost_keys++;
253a9de470cSBruce Richardson 				printf("key %d is lost\n", i);
254a9de470cSBruce Richardson 				break;
255a9de470cSBruce Richardson 			}
256a9de470cSBruce Richardson 		}
257a9de470cSBruce Richardson 	}
258a9de470cSBruce Richardson 
259a9de470cSBruce Richardson 	if (duplicated_keys > 0) {
260a9de470cSBruce Richardson 		printf("%d key duplicated\n", duplicated_keys);
261a9de470cSBruce Richardson 		goto err_free;
262a9de470cSBruce Richardson 	}
263a9de470cSBruce Richardson 
264a9de470cSBruce Richardson 	if (lost_keys > 0) {
265a9de470cSBruce Richardson 		printf("%d key lost\n", lost_keys);
266a9de470cSBruce Richardson 		goto err_free;
267a9de470cSBruce Richardson 	}
268a9de470cSBruce Richardson 
269a9de470cSBruce Richardson 	printf("No key corrupted during read-write test.\n");
270a9de470cSBruce Richardson 
271a9de470cSBruce Richardson 	unsigned long long int cycles_per_insertion =
272*b6a7e685STyler Retzlaff 		rte_atomic_load_explicit(&gcycles, rte_memory_order_relaxed) /
273*b6a7e685STyler Retzlaff 		rte_atomic_load_explicit(&ginsertions, rte_memory_order_relaxed);
274a9de470cSBruce Richardson 
275a9de470cSBruce Richardson 	printf("cycles per insertion and lookup: %llu\n", cycles_per_insertion);
276a9de470cSBruce Richardson 
277a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.found);
278a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.keys);
279a9de470cSBruce Richardson 	rte_hash_free(tbl_rw_test_param.h);
280a9de470cSBruce Richardson 	printf("+++++++++Complete function tests+++++++++\n");
281a9de470cSBruce Richardson 	return 0;
282a9de470cSBruce Richardson 
283a9de470cSBruce Richardson err_free:
284a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.found);
285a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.keys);
286a9de470cSBruce Richardson 	rte_hash_free(tbl_rw_test_param.h);
287a9de470cSBruce Richardson err:
288a9de470cSBruce Richardson 	return -1;
289a9de470cSBruce Richardson }
290a9de470cSBruce Richardson 
291a9de470cSBruce Richardson static int
test_rw_reader(void * arg)292a9de470cSBruce Richardson test_rw_reader(void *arg)
293a9de470cSBruce Richardson {
294a9de470cSBruce Richardson 	uint64_t i;
295a9de470cSBruce Richardson 	uint64_t begin, cycles;
296a9de470cSBruce Richardson 	uint64_t read_cnt = (uint64_t)((uintptr_t)arg);
297a9de470cSBruce Richardson 
298a9de470cSBruce Richardson 	begin = rte_rdtsc_precise();
299a9de470cSBruce Richardson 	for (i = 0; i < read_cnt; i++) {
3001d3bb890SAndrzej Ostruszka 		void *data = arg;
301a9de470cSBruce Richardson 		rte_hash_lookup_data(tbl_rw_test_param.h,
302a9de470cSBruce Richardson 				tbl_rw_test_param.keys + i,
303a9de470cSBruce Richardson 				&data);
304a9de470cSBruce Richardson 		if (i != (uint64_t)(uintptr_t)data) {
305a9de470cSBruce Richardson 			printf("lookup find wrong value %"PRIu64","
306a9de470cSBruce Richardson 				"%"PRIu64"\n", i,
307a9de470cSBruce Richardson 				(uint64_t)(uintptr_t)data);
308a9de470cSBruce Richardson 			break;
309a9de470cSBruce Richardson 		}
310a9de470cSBruce Richardson 	}
311a9de470cSBruce Richardson 
312a9de470cSBruce Richardson 	cycles = rte_rdtsc_precise() - begin;
313*b6a7e685STyler Retzlaff 	rte_atomic_fetch_add_explicit(&gread_cycles, cycles, rte_memory_order_relaxed);
314*b6a7e685STyler Retzlaff 	rte_atomic_fetch_add_explicit(&greads, i, rte_memory_order_relaxed);
315a9de470cSBruce Richardson 	return 0;
316a9de470cSBruce Richardson }
317a9de470cSBruce Richardson 
318a9de470cSBruce Richardson static int
test_rw_writer(void * arg)319a9de470cSBruce Richardson test_rw_writer(void *arg)
320a9de470cSBruce Richardson {
321a9de470cSBruce Richardson 	uint64_t i;
322a9de470cSBruce Richardson 	uint32_t lcore_id = rte_lcore_id();
323a9de470cSBruce Richardson 	uint64_t begin, cycles;
324a9de470cSBruce Richardson 	int ret;
325a9de470cSBruce Richardson 	uint64_t start_coreid = (uint64_t)(uintptr_t)arg;
326a9de470cSBruce Richardson 	uint64_t offset;
327a9de470cSBruce Richardson 
328a9de470cSBruce Richardson 	for (i = 0; i < rte_lcore_count(); i++) {
329cb056611SStephen Hemminger 		if (worker_core_ids[i] == lcore_id)
330a9de470cSBruce Richardson 			break;
331a9de470cSBruce Richardson 	}
332a9de470cSBruce Richardson 
333a9de470cSBruce Richardson 	offset = TOTAL_INSERT / 2 + (i - (start_coreid)) *
334a9de470cSBruce Richardson 				tbl_rw_test_param.num_insert;
335a9de470cSBruce Richardson 	begin = rte_rdtsc_precise();
336a9de470cSBruce Richardson 	for (i = offset; i < offset + tbl_rw_test_param.num_insert; i++) {
337a9de470cSBruce Richardson 		ret = rte_hash_add_key_data(tbl_rw_test_param.h,
338a9de470cSBruce Richardson 				tbl_rw_test_param.keys + i,
339a9de470cSBruce Richardson 				(void *)((uintptr_t)i));
340a9de470cSBruce Richardson 		if (ret < 0) {
341a9de470cSBruce Richardson 			printf("writer failed %"PRIu64"\n", i);
342a9de470cSBruce Richardson 			break;
343a9de470cSBruce Richardson 		}
344a9de470cSBruce Richardson 	}
345a9de470cSBruce Richardson 
346a9de470cSBruce Richardson 	cycles = rte_rdtsc_precise() - begin;
347*b6a7e685STyler Retzlaff 	rte_atomic_fetch_add_explicit(&gwrite_cycles, cycles, rte_memory_order_relaxed);
348*b6a7e685STyler Retzlaff 	rte_atomic_fetch_add_explicit(&gwrites, tbl_rw_test_param.num_insert,
349*b6a7e685STyler Retzlaff 							rte_memory_order_relaxed);
350a9de470cSBruce Richardson 	return 0;
351a9de470cSBruce Richardson }
352a9de470cSBruce Richardson 
353a9de470cSBruce Richardson static int
test_hash_readwrite_perf(struct perf * perf_results,int use_htm,int reader_faster)354a9de470cSBruce Richardson test_hash_readwrite_perf(struct perf *perf_results, int use_htm,
355a9de470cSBruce Richardson 							int reader_faster)
356a9de470cSBruce Richardson {
357a9de470cSBruce Richardson 	unsigned int n;
358a9de470cSBruce Richardson 	int ret;
359a9de470cSBruce Richardson 	int start_coreid;
360a9de470cSBruce Richardson 	uint64_t i, read_cnt;
361a9de470cSBruce Richardson 
362a9de470cSBruce Richardson 	const void *next_key;
363a9de470cSBruce Richardson 	void *next_data;
364a9de470cSBruce Richardson 	uint32_t iter;
365a9de470cSBruce Richardson 	int use_jhash = 0;
366a9de470cSBruce Richardson 
367a9de470cSBruce Richardson 	uint32_t duplicated_keys = 0;
368a9de470cSBruce Richardson 	uint32_t lost_keys = 0;
369a9de470cSBruce Richardson 
370a9de470cSBruce Richardson 	uint64_t start = 0, end = 0;
371a9de470cSBruce Richardson 
372*b6a7e685STyler Retzlaff 	rte_atomic_store_explicit(&gwrites, 0, rte_memory_order_relaxed);
373*b6a7e685STyler Retzlaff 	rte_atomic_store_explicit(&greads, 0, rte_memory_order_relaxed);
374a9de470cSBruce Richardson 
375*b6a7e685STyler Retzlaff 	rte_atomic_store_explicit(&gread_cycles, 0, rte_memory_order_relaxed);
376*b6a7e685STyler Retzlaff 	rte_atomic_store_explicit(&gwrite_cycles, 0, rte_memory_order_relaxed);
377a9de470cSBruce Richardson 
37803a0ed1aSHonnappa Nagarahalli 	if (init_params(0, use_htm, 0, use_jhash) != 0)
379a9de470cSBruce Richardson 		goto err;
380a9de470cSBruce Richardson 
381a9de470cSBruce Richardson 	/*
382a9de470cSBruce Richardson 	 * Do a readers finish faster or writers finish faster test.
383a9de470cSBruce Richardson 	 * When readers finish faster, we timing the readers, and when writers
384a9de470cSBruce Richardson 	 * finish faster, we timing the writers.
385a9de470cSBruce Richardson 	 * Divided by 10 or 2 is just experimental values to vary the workload
386a9de470cSBruce Richardson 	 * of readers.
387a9de470cSBruce Richardson 	 */
388a9de470cSBruce Richardson 	if (reader_faster) {
389a9de470cSBruce Richardson 		printf("++++++Start perf test: reader++++++++\n");
390a9de470cSBruce Richardson 		read_cnt = TOTAL_INSERT / 10;
391a9de470cSBruce Richardson 	} else {
392a9de470cSBruce Richardson 		printf("++++++Start perf test: writer++++++++\n");
393a9de470cSBruce Richardson 		read_cnt = TOTAL_INSERT / 2;
394a9de470cSBruce Richardson 	}
395a9de470cSBruce Richardson 
396a9de470cSBruce Richardson 	/* We first test single thread performance */
397a9de470cSBruce Richardson 	start = rte_rdtsc_precise();
398a9de470cSBruce Richardson 	/* Insert half of the keys */
399a9de470cSBruce Richardson 	for (i = 0; i < TOTAL_INSERT / 2; i++) {
400a9de470cSBruce Richardson 		ret = rte_hash_add_key_data(tbl_rw_test_param.h,
401a9de470cSBruce Richardson 				     tbl_rw_test_param.keys + i,
402a9de470cSBruce Richardson 					(void *)((uintptr_t)i));
403a9de470cSBruce Richardson 		if (ret < 0) {
404a9de470cSBruce Richardson 			printf("Failed to insert half of keys\n");
405a9de470cSBruce Richardson 			goto err_free;
406a9de470cSBruce Richardson 		}
407a9de470cSBruce Richardson 	}
408a9de470cSBruce Richardson 	end = rte_rdtsc_precise() - start;
409a9de470cSBruce Richardson 	perf_results->single_write = end / i;
410a9de470cSBruce Richardson 
411a9de470cSBruce Richardson 	start = rte_rdtsc_precise();
412a9de470cSBruce Richardson 
413a9de470cSBruce Richardson 	for (i = 0; i < read_cnt; i++) {
414a9de470cSBruce Richardson 		void *data;
415a9de470cSBruce Richardson 		rte_hash_lookup_data(tbl_rw_test_param.h,
416a9de470cSBruce Richardson 				tbl_rw_test_param.keys + i,
417a9de470cSBruce Richardson 				&data);
418a9de470cSBruce Richardson 		if (i != (uint64_t)(uintptr_t)data) {
419a9de470cSBruce Richardson 			printf("lookup find wrong value"
420a9de470cSBruce Richardson 					" %"PRIu64",%"PRIu64"\n", i,
421a9de470cSBruce Richardson 					(uint64_t)(uintptr_t)data);
422a9de470cSBruce Richardson 			break;
423a9de470cSBruce Richardson 		}
424a9de470cSBruce Richardson 	}
425a9de470cSBruce Richardson 	end = rte_rdtsc_precise() - start;
426a9de470cSBruce Richardson 	perf_results->single_read = end / i;
427a9de470cSBruce Richardson 
428a9de470cSBruce Richardson 	for (n = 0; n < NUM_TEST; n++) {
429cb056611SStephen Hemminger 		unsigned int tot_worker_lcore = rte_lcore_count() - 1;
430cb056611SStephen Hemminger 		if (tot_worker_lcore < core_cnt[n] * 2)
431a9de470cSBruce Richardson 			goto finish;
432a9de470cSBruce Richardson 
433*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&greads, 0, rte_memory_order_relaxed);
434*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&gread_cycles, 0, rte_memory_order_relaxed);
435*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&gwrites, 0, rte_memory_order_relaxed);
436*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&gwrite_cycles, 0, rte_memory_order_relaxed);
437a9de470cSBruce Richardson 
438a9de470cSBruce Richardson 		rte_hash_reset(tbl_rw_test_param.h);
439a9de470cSBruce Richardson 
440a9de470cSBruce Richardson 		tbl_rw_test_param.num_insert = TOTAL_INSERT / 2 / core_cnt[n];
441a9de470cSBruce Richardson 		tbl_rw_test_param.rounded_tot_insert = TOTAL_INSERT / 2 +
442a9de470cSBruce Richardson 						tbl_rw_test_param.num_insert *
443a9de470cSBruce Richardson 						core_cnt[n];
444a9de470cSBruce Richardson 
445a9de470cSBruce Richardson 		for (i = 0; i < TOTAL_INSERT / 2; i++) {
446a9de470cSBruce Richardson 			ret = rte_hash_add_key_data(tbl_rw_test_param.h,
447a9de470cSBruce Richardson 					tbl_rw_test_param.keys + i,
448a9de470cSBruce Richardson 					(void *)((uintptr_t)i));
449a9de470cSBruce Richardson 			if (ret < 0) {
450a9de470cSBruce Richardson 				printf("Failed to insert half of keys\n");
451a9de470cSBruce Richardson 				goto err_free;
452a9de470cSBruce Richardson 			}
453a9de470cSBruce Richardson 		}
454a9de470cSBruce Richardson 
455a9de470cSBruce Richardson 		/* Then test multiple thread case but only all reads or
456a9de470cSBruce Richardson 		 * all writes
457a9de470cSBruce Richardson 		 */
458a9de470cSBruce Richardson 
459a9de470cSBruce Richardson 		/* Test only reader cases */
460a9de470cSBruce Richardson 		for (i = 0; i < core_cnt[n]; i++)
461a9de470cSBruce Richardson 			rte_eal_remote_launch(test_rw_reader,
462a9de470cSBruce Richardson 					(void *)(uintptr_t)read_cnt,
463cb056611SStephen Hemminger 					worker_core_ids[i]);
464a9de470cSBruce Richardson 
465a9de470cSBruce Richardson 		rte_eal_mp_wait_lcore();
466a9de470cSBruce Richardson 
467a9de470cSBruce Richardson 		start_coreid = i;
468a9de470cSBruce Richardson 		/* Test only writer cases */
469a9de470cSBruce Richardson 		for (; i < core_cnt[n] * 2; i++)
470a9de470cSBruce Richardson 			rte_eal_remote_launch(test_rw_writer,
471a9de470cSBruce Richardson 					(void *)((uintptr_t)start_coreid),
472cb056611SStephen Hemminger 					worker_core_ids[i]);
473a9de470cSBruce Richardson 
474a9de470cSBruce Richardson 		rte_eal_mp_wait_lcore();
475a9de470cSBruce Richardson 
476a9de470cSBruce Richardson 		if (reader_faster) {
477a9de470cSBruce Richardson 			unsigned long long int cycles_per_insertion =
478*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&gread_cycles, rte_memory_order_relaxed) /
479*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&greads, rte_memory_order_relaxed);
480a9de470cSBruce Richardson 			perf_results->read_only[n] = cycles_per_insertion;
481a9de470cSBruce Richardson 			printf("Reader only: cycles per lookup: %llu\n",
482a9de470cSBruce Richardson 							cycles_per_insertion);
483a9de470cSBruce Richardson 		}
484a9de470cSBruce Richardson 
485a9de470cSBruce Richardson 		else {
486a9de470cSBruce Richardson 			unsigned long long int cycles_per_insertion =
487*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&gwrite_cycles, rte_memory_order_relaxed) /
488*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&gwrites, rte_memory_order_relaxed);
489a9de470cSBruce Richardson 			perf_results->write_only[n] = cycles_per_insertion;
490a9de470cSBruce Richardson 			printf("Writer only: cycles per writes: %llu\n",
491a9de470cSBruce Richardson 							cycles_per_insertion);
492a9de470cSBruce Richardson 		}
493a9de470cSBruce Richardson 
494*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&greads, 0, rte_memory_order_relaxed);
495*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&gread_cycles, 0, rte_memory_order_relaxed);
496*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&gwrites, 0, rte_memory_order_relaxed);
497*b6a7e685STyler Retzlaff 		rte_atomic_store_explicit(&gwrite_cycles, 0, rte_memory_order_relaxed);
498a9de470cSBruce Richardson 
499a9de470cSBruce Richardson 		rte_hash_reset(tbl_rw_test_param.h);
500a9de470cSBruce Richardson 
501a9de470cSBruce Richardson 		for (i = 0; i < TOTAL_INSERT / 2; i++) {
502a9de470cSBruce Richardson 			ret = rte_hash_add_key_data(tbl_rw_test_param.h,
503a9de470cSBruce Richardson 					tbl_rw_test_param.keys + i,
504a9de470cSBruce Richardson 					(void *)((uintptr_t)i));
505a9de470cSBruce Richardson 			if (ret < 0) {
506a9de470cSBruce Richardson 				printf("Failed to insert half of keys\n");
507a9de470cSBruce Richardson 				goto err_free;
508a9de470cSBruce Richardson 			}
509a9de470cSBruce Richardson 		}
510a9de470cSBruce Richardson 
511a9de470cSBruce Richardson 		start_coreid = core_cnt[n];
512a9de470cSBruce Richardson 
513a9de470cSBruce Richardson 		if (reader_faster) {
514a9de470cSBruce Richardson 			for (i = core_cnt[n]; i < core_cnt[n] * 2; i++)
515a9de470cSBruce Richardson 				rte_eal_remote_launch(test_rw_writer,
516a9de470cSBruce Richardson 					(void *)((uintptr_t)start_coreid),
517cb056611SStephen Hemminger 					worker_core_ids[i]);
518a9de470cSBruce Richardson 			for (i = 0; i < core_cnt[n]; i++)
519a9de470cSBruce Richardson 				rte_eal_remote_launch(test_rw_reader,
520a9de470cSBruce Richardson 					(void *)(uintptr_t)read_cnt,
521cb056611SStephen Hemminger 					worker_core_ids[i]);
522a9de470cSBruce Richardson 		} else {
523a9de470cSBruce Richardson 			for (i = 0; i < core_cnt[n]; i++)
524a9de470cSBruce Richardson 				rte_eal_remote_launch(test_rw_reader,
525a9de470cSBruce Richardson 					(void *)(uintptr_t)read_cnt,
526cb056611SStephen Hemminger 					worker_core_ids[i]);
527a9de470cSBruce Richardson 			for (; i < core_cnt[n] * 2; i++)
528a9de470cSBruce Richardson 				rte_eal_remote_launch(test_rw_writer,
529a9de470cSBruce Richardson 					(void *)((uintptr_t)start_coreid),
530cb056611SStephen Hemminger 					worker_core_ids[i]);
531a9de470cSBruce Richardson 		}
532a9de470cSBruce Richardson 
533a9de470cSBruce Richardson 		rte_eal_mp_wait_lcore();
534a9de470cSBruce Richardson 
535a9de470cSBruce Richardson 		iter = 0;
536a9de470cSBruce Richardson 		memset(tbl_rw_test_param.found, 0, TOTAL_ENTRY);
537a9de470cSBruce Richardson 		while (rte_hash_iterate(tbl_rw_test_param.h,
538a9de470cSBruce Richardson 				&next_key, &next_data, &iter) >= 0) {
539a9de470cSBruce Richardson 			/* Search for the key in the list of keys added .*/
540a9de470cSBruce Richardson 			i = *(const uint32_t *)next_key;
541a9de470cSBruce Richardson 			tbl_rw_test_param.found[i]++;
542a9de470cSBruce Richardson 		}
543a9de470cSBruce Richardson 
544a9de470cSBruce Richardson 		for (i = 0; i < tbl_rw_test_param.rounded_tot_insert; i++) {
545a9de470cSBruce Richardson 			if (tbl_rw_test_param.keys[i] != RTE_RWTEST_FAIL) {
546a9de470cSBruce Richardson 				if (tbl_rw_test_param.found[i] > 1) {
547a9de470cSBruce Richardson 					duplicated_keys++;
548a9de470cSBruce Richardson 					break;
549a9de470cSBruce Richardson 				}
550a9de470cSBruce Richardson 				if (tbl_rw_test_param.found[i] == 0) {
551a9de470cSBruce Richardson 					lost_keys++;
552a9de470cSBruce Richardson 					printf("key %"PRIu64" is lost\n", i);
553a9de470cSBruce Richardson 					break;
554a9de470cSBruce Richardson 				}
555a9de470cSBruce Richardson 			}
556a9de470cSBruce Richardson 		}
557a9de470cSBruce Richardson 
558a9de470cSBruce Richardson 		if (duplicated_keys > 0) {
559a9de470cSBruce Richardson 			printf("%d key duplicated\n", duplicated_keys);
560a9de470cSBruce Richardson 			goto err_free;
561a9de470cSBruce Richardson 		}
562a9de470cSBruce Richardson 
563a9de470cSBruce Richardson 		if (lost_keys > 0) {
564a9de470cSBruce Richardson 			printf("%d key lost\n", lost_keys);
565a9de470cSBruce Richardson 			goto err_free;
566a9de470cSBruce Richardson 		}
567a9de470cSBruce Richardson 
568a9de470cSBruce Richardson 		printf("No key corrupted during read-write test.\n");
569a9de470cSBruce Richardson 
570a9de470cSBruce Richardson 		if (reader_faster) {
571a9de470cSBruce Richardson 			unsigned long long int cycles_per_insertion =
572*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&gread_cycles, rte_memory_order_relaxed) /
573*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&greads, rte_memory_order_relaxed);
574a9de470cSBruce Richardson 			perf_results->read_write_r[n] = cycles_per_insertion;
575a9de470cSBruce Richardson 			printf("Read-write cycles per lookup: %llu\n",
576a9de470cSBruce Richardson 							cycles_per_insertion);
577a9de470cSBruce Richardson 		}
578a9de470cSBruce Richardson 
579a9de470cSBruce Richardson 		else {
580a9de470cSBruce Richardson 			unsigned long long int cycles_per_insertion =
581*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&gwrite_cycles, rte_memory_order_relaxed) /
582*b6a7e685STyler Retzlaff 				rte_atomic_load_explicit(&gwrites, rte_memory_order_relaxed);
583a9de470cSBruce Richardson 			perf_results->read_write_w[n] = cycles_per_insertion;
584a9de470cSBruce Richardson 			printf("Read-write cycles per writes: %llu\n",
585a9de470cSBruce Richardson 							cycles_per_insertion);
586a9de470cSBruce Richardson 		}
587a9de470cSBruce Richardson 	}
588a9de470cSBruce Richardson 
589a9de470cSBruce Richardson finish:
590a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.found);
591a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.keys);
592a9de470cSBruce Richardson 	rte_hash_free(tbl_rw_test_param.h);
593a9de470cSBruce Richardson 	return 0;
594a9de470cSBruce Richardson 
595a9de470cSBruce Richardson err_free:
596a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.found);
597a9de470cSBruce Richardson 	rte_free(tbl_rw_test_param.keys);
598a9de470cSBruce Richardson 	rte_hash_free(tbl_rw_test_param.h);
599a9de470cSBruce Richardson 
600a9de470cSBruce Richardson err:
601a9de470cSBruce Richardson 	return -1;
602a9de470cSBruce Richardson }
603a9de470cSBruce Richardson 
604a9de470cSBruce Richardson static int
test_hash_rw_perf_main(void)605f6208425SAmit Gupta test_hash_rw_perf_main(void)
606a9de470cSBruce Richardson {
607a9de470cSBruce Richardson 	/*
608a9de470cSBruce Richardson 	 * Variables used to choose different tests.
609a9de470cSBruce Richardson 	 * use_htm indicates if hardware transactional memory should be used.
610a9de470cSBruce Richardson 	 * reader_faster indicates if the reader threads should finish earlier
611a9de470cSBruce Richardson 	 * than writer threads. This is to timing either reader threads or
612a9de470cSBruce Richardson 	 * writer threads for performance numbers.
613a9de470cSBruce Richardson 	 */
614f6208425SAmit Gupta 	int use_htm, reader_faster;
615a9de470cSBruce Richardson 	unsigned int i = 0, core_id = 0;
616a9de470cSBruce Richardson 
617e0f4a0edSDavid Marchand 	if (rte_lcore_count() < 3) {
618e0f4a0edSDavid Marchand 		printf("Not enough cores for hash_readwrite_autotest, expecting at least 3\n");
619e0f4a0edSDavid Marchand 		return TEST_SKIPPED;
620a9de470cSBruce Richardson 	}
621a9de470cSBruce Richardson 
622cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(core_id) {
623cb056611SStephen Hemminger 		worker_core_ids[i] = core_id;
624a9de470cSBruce Richardson 		i++;
625a9de470cSBruce Richardson 	}
626a9de470cSBruce Richardson 
627a9de470cSBruce Richardson 	setlocale(LC_NUMERIC, "");
628a9de470cSBruce Richardson 
629a9de470cSBruce Richardson 	if (rte_tm_supported()) {
630a9de470cSBruce Richardson 		printf("Hardware transactional memory (lock elision) "
631a9de470cSBruce Richardson 			"is supported\n");
632a9de470cSBruce Richardson 
633a9de470cSBruce Richardson 		printf("Test read-write with Hardware transactional memory\n");
634a9de470cSBruce Richardson 
635a9de470cSBruce Richardson 		use_htm = 1;
636a9de470cSBruce Richardson 
637a9de470cSBruce Richardson 		reader_faster = 1;
638a9de470cSBruce Richardson 		if (test_hash_readwrite_perf(&htm_results, use_htm,
639a9de470cSBruce Richardson 							reader_faster) < 0)
640a9de470cSBruce Richardson 			return -1;
641a9de470cSBruce Richardson 
642a9de470cSBruce Richardson 		reader_faster = 0;
643a9de470cSBruce Richardson 		if (test_hash_readwrite_perf(&htm_results, use_htm,
644a9de470cSBruce Richardson 							reader_faster) < 0)
645a9de470cSBruce Richardson 			return -1;
646a9de470cSBruce Richardson 	} else {
647a9de470cSBruce Richardson 		printf("Hardware transactional memory (lock elision) "
648a9de470cSBruce Richardson 			"is NOT supported\n");
649a9de470cSBruce Richardson 	}
650a9de470cSBruce Richardson 
651a9de470cSBruce Richardson 	printf("Test read-write without Hardware transactional memory\n");
652a9de470cSBruce Richardson 	use_htm = 0;
653a9de470cSBruce Richardson 
654a9de470cSBruce Richardson 	reader_faster = 1;
655a9de470cSBruce Richardson 	if (test_hash_readwrite_perf(&non_htm_results, use_htm,
656a9de470cSBruce Richardson 							reader_faster) < 0)
657a9de470cSBruce Richardson 		return -1;
658a9de470cSBruce Richardson 	reader_faster = 0;
659a9de470cSBruce Richardson 	if (test_hash_readwrite_perf(&non_htm_results, use_htm,
660a9de470cSBruce Richardson 							reader_faster) < 0)
661a9de470cSBruce Richardson 		return -1;
662a9de470cSBruce Richardson 
663a9de470cSBruce Richardson 	printf("================\n");
664a9de470cSBruce Richardson 	printf("Results summary:\n");
665a9de470cSBruce Richardson 	printf("================\n");
666a9de470cSBruce Richardson 
667af0892afSStanislaw Kardach 	printf("HTM:\n");
668a9de470cSBruce Richardson 	printf("  single read: %u\n", htm_results.single_read);
669a9de470cSBruce Richardson 	printf("  single write: %u\n", htm_results.single_write);
670af0892afSStanislaw Kardach 	printf("non HTM:\n");
671af0892afSStanislaw Kardach 	printf("  single read: %u\n", non_htm_results.single_read);
672af0892afSStanislaw Kardach 	printf("  single write: %u\n", non_htm_results.single_write);
673a9de470cSBruce Richardson 	for (i = 0; i < NUM_TEST; i++) {
674a9de470cSBruce Richardson 		printf("+++ core_cnt: %u +++\n", core_cnt[i]);
675a9de470cSBruce Richardson 		printf("HTM:\n");
676a9de470cSBruce Richardson 		printf("  read only: %u\n", htm_results.read_only[i]);
677a9de470cSBruce Richardson 		printf("  write only: %u\n", htm_results.write_only[i]);
678a9de470cSBruce Richardson 		printf("  read-write read: %u\n", htm_results.read_write_r[i]);
679a9de470cSBruce Richardson 		printf("  read-write write: %u\n", htm_results.read_write_w[i]);
680a9de470cSBruce Richardson 
681a9de470cSBruce Richardson 		printf("non HTM:\n");
682a9de470cSBruce Richardson 		printf("  read only: %u\n", non_htm_results.read_only[i]);
683a9de470cSBruce Richardson 		printf("  write only: %u\n", non_htm_results.write_only[i]);
684a9de470cSBruce Richardson 		printf("  read-write read: %u\n",
685a9de470cSBruce Richardson 			non_htm_results.read_write_r[i]);
686a9de470cSBruce Richardson 		printf("  read-write write: %u\n",
687a9de470cSBruce Richardson 			non_htm_results.read_write_w[i]);
688a9de470cSBruce Richardson 	}
689a9de470cSBruce Richardson 
690a9de470cSBruce Richardson 	return 0;
691a9de470cSBruce Richardson }
692a9de470cSBruce Richardson 
693f6208425SAmit Gupta static int
test_hash_rw_func_main(void)694f6208425SAmit Gupta test_hash_rw_func_main(void)
695f6208425SAmit Gupta {
696f6208425SAmit Gupta 	/*
697f6208425SAmit Gupta 	 * Variables used to choose different tests.
698f6208425SAmit Gupta 	 * use_htm indicates if hardware transactional memory should be used.
699f6208425SAmit Gupta 	 * reader_faster indicates if the reader threads should finish earlier
700f6208425SAmit Gupta 	 * than writer threads. This is to timing either reader threads or
701f6208425SAmit Gupta 	 * writer threads for performance numbers.
702f6208425SAmit Gupta 	 */
703f6208425SAmit Gupta 	unsigned int i = 0, core_id = 0;
704f6208425SAmit Gupta 
705f6208425SAmit Gupta 	if (rte_lcore_count() < 3) {
706f6208425SAmit Gupta 		printf("Not enough cores for hash_readwrite_autotest, expecting at least 3\n");
707f6208425SAmit Gupta 		return TEST_SKIPPED;
708f6208425SAmit Gupta 	}
709f6208425SAmit Gupta 
710cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(core_id) {
711cb056611SStephen Hemminger 		worker_core_ids[i] = core_id;
712f6208425SAmit Gupta 		i++;
713f6208425SAmit Gupta 	}
714f6208425SAmit Gupta 
715f6208425SAmit Gupta 	setlocale(LC_NUMERIC, "");
716f6208425SAmit Gupta 
717f6208425SAmit Gupta 	if (rte_tm_supported()) {
718f6208425SAmit Gupta 		printf("Hardware transactional memory (lock elision) "
719f6208425SAmit Gupta 			"is supported\n");
720f6208425SAmit Gupta 
721f6208425SAmit Gupta 		printf("Test read-write with Hardware transactional memory\n");
722f6208425SAmit Gupta 
72303a0ed1aSHonnappa Nagarahalli 		/* htm = 1, rw_lf = 0, ext = 0 */
72403a0ed1aSHonnappa Nagarahalli 		if (test_hash_readwrite_functional(1, 0, 0) < 0)
725f6208425SAmit Gupta 			return -1;
726f6208425SAmit Gupta 
72703a0ed1aSHonnappa Nagarahalli 		/* htm = 1, rw_lf = 1, ext = 0 */
72803a0ed1aSHonnappa Nagarahalli 		if (test_hash_readwrite_functional(1, 1, 0) < 0)
729f6208425SAmit Gupta 			return -1;
730f6208425SAmit Gupta 
73103a0ed1aSHonnappa Nagarahalli 		/* htm = 1, rw_lf = 0, ext = 1 */
73203a0ed1aSHonnappa Nagarahalli 		if (test_hash_readwrite_functional(1, 0, 1) < 0)
73303a0ed1aSHonnappa Nagarahalli 			return -1;
73403a0ed1aSHonnappa Nagarahalli 
73503a0ed1aSHonnappa Nagarahalli 		/* htm = 1, rw_lf = 1, ext = 1 */
73603a0ed1aSHonnappa Nagarahalli 		if (test_hash_readwrite_functional(1, 1, 1) < 0)
73703a0ed1aSHonnappa Nagarahalli 			return -1;
738f6208425SAmit Gupta 	} else {
739f6208425SAmit Gupta 		printf("Hardware transactional memory (lock elision) "
740f6208425SAmit Gupta 			"is NOT supported\n");
741f6208425SAmit Gupta 	}
742f6208425SAmit Gupta 
743f6208425SAmit Gupta 	printf("Test read-write without Hardware transactional memory\n");
74403a0ed1aSHonnappa Nagarahalli 	/* htm = 0, rw_lf = 0, ext = 0 */
74503a0ed1aSHonnappa Nagarahalli 	if (test_hash_readwrite_functional(0, 0, 0) < 0)
746f6208425SAmit Gupta 		return -1;
747f6208425SAmit Gupta 
74803a0ed1aSHonnappa Nagarahalli 	/* htm = 0, rw_lf = 1, ext = 0 */
74903a0ed1aSHonnappa Nagarahalli 	if (test_hash_readwrite_functional(0, 1, 0) < 0)
75003a0ed1aSHonnappa Nagarahalli 		return -1;
75103a0ed1aSHonnappa Nagarahalli 
75203a0ed1aSHonnappa Nagarahalli 	/* htm = 0, rw_lf = 0, ext = 1 */
75303a0ed1aSHonnappa Nagarahalli 	if (test_hash_readwrite_functional(0, 0, 1) < 0)
75403a0ed1aSHonnappa Nagarahalli 		return -1;
75503a0ed1aSHonnappa Nagarahalli 
75603a0ed1aSHonnappa Nagarahalli 	/* htm = 0, rw_lf = 1, ext = 1 */
75703a0ed1aSHonnappa Nagarahalli 	if (test_hash_readwrite_functional(0, 1, 1) < 0)
758f6208425SAmit Gupta 		return -1;
759f6208425SAmit Gupta 
760f6208425SAmit Gupta 	return 0;
761f6208425SAmit Gupta }
762f6208425SAmit Gupta 
763e0a8442cSBruce Richardson REGISTER_FAST_TEST(hash_readwrite_func_autotest, false, true, test_hash_rw_func_main);
764e0a8442cSBruce Richardson REGISTER_PERF_TEST(hash_readwrite_perf_autotest, test_hash_rw_perf_main);
765