]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2016 Intel Corporation | |
7c673cae | 3 | */ |
11fdf7f2 | 4 | |
7c673cae FG |
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_launch.h> | |
12 | #include <rte_malloc.h> | |
13 | #include <rte_random.h> | |
14 | #include <rte_spinlock.h> | |
15 | ||
16 | #include "test.h" | |
17 | ||
18 | /* | |
19 | * Check condition and return an error if true. Assumes that "handle" is the | |
20 | * name of the hash structure pointer to be freed. | |
21 | */ | |
22 | #define RETURN_IF_ERROR(cond, str, ...) do { \ | |
23 | if (cond) { \ | |
24 | printf("ERROR line %d: " str "\n", __LINE__, \ | |
25 | ##__VA_ARGS__); \ | |
26 | if (handle) \ | |
27 | rte_hash_free(handle); \ | |
28 | return -1; \ | |
29 | } \ | |
30 | } while (0) | |
31 | ||
32 | #define RTE_APP_TEST_HASH_MULTIWRITER_FAILED 0 | |
33 | ||
34 | struct { | |
35 | uint32_t *keys; | |
36 | uint32_t *found; | |
37 | uint32_t nb_tsx_insertion; | |
38 | struct rte_hash *h; | |
39 | } tbl_multiwriter_test_params; | |
40 | ||
41 | const uint32_t nb_entries = 16*1024*1024; | |
42 | const uint32_t nb_total_tsx_insertion = 15*1024*1024; | |
43 | uint32_t rounded_nb_total_tsx_insertion; | |
44 | ||
45 | static rte_atomic64_t gcycles; | |
46 | static rte_atomic64_t ginsertions; | |
47 | ||
48 | static int use_htm; | |
49 | ||
50 | static int | |
11fdf7f2 | 51 | test_hash_multiwriter_worker(void *arg) |
7c673cae FG |
52 | { |
53 | uint64_t i, offset; | |
11fdf7f2 | 54 | uint16_t pos_core; |
7c673cae FG |
55 | uint32_t lcore_id = rte_lcore_id(); |
56 | uint64_t begin, cycles; | |
11fdf7f2 | 57 | uint16_t *enabled_core_ids = (uint16_t *)arg; |
7c673cae | 58 | |
11fdf7f2 TL |
59 | for (pos_core = 0; pos_core < rte_lcore_count(); pos_core++) { |
60 | if (enabled_core_ids[pos_core] == lcore_id) | |
61 | break; | |
62 | } | |
63 | ||
64 | /* | |
65 | * Calculate offset for entries based on the position of the | |
66 | * logical core, from the master core (not counting not enabled cores) | |
67 | */ | |
68 | offset = pos_core * tbl_multiwriter_test_params.nb_tsx_insertion; | |
7c673cae FG |
69 | |
70 | printf("Core #%d inserting %d: %'"PRId64" - %'"PRId64"\n", | |
71 | lcore_id, tbl_multiwriter_test_params.nb_tsx_insertion, | |
11fdf7f2 TL |
72 | offset, |
73 | offset + tbl_multiwriter_test_params.nb_tsx_insertion - 1); | |
7c673cae FG |
74 | |
75 | begin = rte_rdtsc_precise(); | |
76 | ||
77 | for (i = offset; | |
78 | i < offset + tbl_multiwriter_test_params.nb_tsx_insertion; | |
79 | i++) { | |
80 | if (rte_hash_add_key(tbl_multiwriter_test_params.h, | |
81 | tbl_multiwriter_test_params.keys + i) < 0) | |
82 | break; | |
83 | } | |
84 | ||
85 | cycles = rte_rdtsc_precise() - begin; | |
86 | rte_atomic64_add(&gcycles, cycles); | |
87 | rte_atomic64_add(&ginsertions, i - offset); | |
88 | ||
89 | for (; i < offset + tbl_multiwriter_test_params.nb_tsx_insertion; i++) | |
90 | tbl_multiwriter_test_params.keys[i] | |
91 | = RTE_APP_TEST_HASH_MULTIWRITER_FAILED; | |
92 | ||
93 | return 0; | |
94 | } | |
95 | ||
96 | ||
97 | static int | |
98 | test_hash_multiwriter(void) | |
99 | { | |
100 | unsigned int i, rounded_nb_total_tsx_insertion; | |
101 | static unsigned calledCount = 1; | |
11fdf7f2 TL |
102 | uint16_t enabled_core_ids[RTE_MAX_LCORE]; |
103 | uint16_t core_id; | |
7c673cae FG |
104 | |
105 | uint32_t *keys; | |
106 | uint32_t *found; | |
107 | ||
108 | struct rte_hash_parameters hash_params = { | |
109 | .entries = nb_entries, | |
110 | .key_len = sizeof(uint32_t), | |
111 | .hash_func = rte_hash_crc, | |
112 | .hash_func_init_val = 0, | |
113 | .socket_id = rte_socket_id(), | |
114 | }; | |
115 | if (use_htm) | |
116 | hash_params.extra_flag = | |
117 | RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT | |
118 | | RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD; | |
119 | else | |
120 | hash_params.extra_flag = | |
121 | RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD; | |
122 | ||
123 | struct rte_hash *handle; | |
124 | char name[RTE_HASH_NAMESIZE]; | |
125 | ||
126 | const void *next_key; | |
127 | void *next_data; | |
128 | uint32_t iter = 0; | |
129 | ||
130 | uint32_t duplicated_keys = 0; | |
131 | uint32_t lost_keys = 0; | |
11fdf7f2 | 132 | uint32_t count; |
7c673cae FG |
133 | |
134 | snprintf(name, 32, "test%u", calledCount++); | |
135 | hash_params.name = name; | |
136 | ||
137 | handle = rte_hash_create(&hash_params); | |
138 | RETURN_IF_ERROR(handle == NULL, "hash creation failed"); | |
139 | ||
140 | tbl_multiwriter_test_params.h = handle; | |
141 | tbl_multiwriter_test_params.nb_tsx_insertion = | |
142 | nb_total_tsx_insertion / rte_lcore_count(); | |
143 | ||
144 | rounded_nb_total_tsx_insertion = (nb_total_tsx_insertion / | |
145 | tbl_multiwriter_test_params.nb_tsx_insertion) | |
146 | * tbl_multiwriter_test_params.nb_tsx_insertion; | |
147 | ||
148 | rte_srand(rte_rdtsc()); | |
149 | ||
150 | keys = rte_malloc(NULL, sizeof(uint32_t) * nb_entries, 0); | |
151 | ||
152 | if (keys == NULL) { | |
153 | printf("RTE_MALLOC failed\n"); | |
154 | goto err1; | |
155 | } | |
156 | ||
11fdf7f2 TL |
157 | for (i = 0; i < nb_entries; i++) |
158 | keys[i] = i; | |
159 | ||
160 | tbl_multiwriter_test_params.keys = keys; | |
161 | ||
7c673cae FG |
162 | found = rte_zmalloc(NULL, sizeof(uint32_t) * nb_entries, 0); |
163 | if (found == NULL) { | |
164 | printf("RTE_ZMALLOC failed\n"); | |
165 | goto err2; | |
166 | } | |
167 | ||
7c673cae FG |
168 | tbl_multiwriter_test_params.found = found; |
169 | ||
170 | rte_atomic64_init(&gcycles); | |
171 | rte_atomic64_clear(&gcycles); | |
172 | ||
173 | rte_atomic64_init(&ginsertions); | |
174 | rte_atomic64_clear(&ginsertions); | |
175 | ||
11fdf7f2 TL |
176 | /* Get list of enabled cores */ |
177 | i = 0; | |
178 | for (core_id = 0; core_id < RTE_MAX_LCORE; core_id++) { | |
179 | if (i == rte_lcore_count()) | |
180 | break; | |
181 | ||
182 | if (rte_lcore_is_enabled(core_id)) { | |
183 | enabled_core_ids[i] = core_id; | |
184 | i++; | |
185 | } | |
186 | } | |
187 | ||
188 | if (i != rte_lcore_count()) { | |
189 | printf("Number of enabled cores in list is different from " | |
190 | "number given by rte_lcore_count()\n"); | |
191 | goto err3; | |
192 | } | |
193 | ||
7c673cae FG |
194 | /* Fire all threads. */ |
195 | rte_eal_mp_remote_launch(test_hash_multiwriter_worker, | |
11fdf7f2 | 196 | enabled_core_ids, CALL_MASTER); |
7c673cae FG |
197 | rte_eal_mp_wait_lcore(); |
198 | ||
11fdf7f2 TL |
199 | count = rte_hash_count(handle); |
200 | if (count != rounded_nb_total_tsx_insertion) { | |
201 | printf("rte_hash_count returned wrong value %u, %d\n", | |
202 | rounded_nb_total_tsx_insertion, count); | |
203 | goto err3; | |
204 | } | |
205 | ||
7c673cae FG |
206 | while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) { |
207 | /* Search for the key in the list of keys added .*/ | |
208 | i = *(const uint32_t *)next_key; | |
209 | tbl_multiwriter_test_params.found[i]++; | |
210 | } | |
211 | ||
212 | for (i = 0; i < rounded_nb_total_tsx_insertion; i++) { | |
213 | if (tbl_multiwriter_test_params.keys[i] | |
214 | != RTE_APP_TEST_HASH_MULTIWRITER_FAILED) { | |
215 | if (tbl_multiwriter_test_params.found[i] > 1) { | |
216 | duplicated_keys++; | |
217 | break; | |
218 | } | |
219 | if (tbl_multiwriter_test_params.found[i] == 0) { | |
220 | lost_keys++; | |
221 | printf("key %d is lost\n", i); | |
222 | break; | |
223 | } | |
224 | } | |
225 | } | |
226 | ||
227 | if (duplicated_keys > 0) { | |
228 | printf("%d key duplicated\n", duplicated_keys); | |
229 | goto err3; | |
230 | } | |
231 | ||
232 | if (lost_keys > 0) { | |
233 | printf("%d key lost\n", lost_keys); | |
234 | goto err3; | |
235 | } | |
236 | ||
237 | printf("No key corrupted during multiwriter insertion.\n"); | |
238 | ||
239 | unsigned long long int cycles_per_insertion = | |
240 | rte_atomic64_read(&gcycles)/ | |
241 | rte_atomic64_read(&ginsertions); | |
242 | ||
243 | printf(" cycles per insertion: %llu\n", cycles_per_insertion); | |
244 | ||
245 | rte_free(tbl_multiwriter_test_params.found); | |
246 | rte_free(tbl_multiwriter_test_params.keys); | |
247 | rte_hash_free(handle); | |
248 | return 0; | |
249 | ||
250 | err3: | |
251 | rte_free(tbl_multiwriter_test_params.found); | |
252 | err2: | |
253 | rte_free(tbl_multiwriter_test_params.keys); | |
254 | err1: | |
255 | rte_hash_free(handle); | |
256 | return -1; | |
257 | } | |
258 | ||
259 | static int | |
260 | test_hash_multiwriter_main(void) | |
261 | { | |
262 | if (rte_lcore_count() == 1) { | |
263 | printf("More than one lcore is required to do multiwriter test\n"); | |
264 | return 0; | |
265 | } | |
266 | ||
267 | ||
268 | setlocale(LC_NUMERIC, ""); | |
269 | ||
270 | ||
271 | if (!rte_tm_supported()) { | |
272 | printf("Hardware transactional memory (lock elision) " | |
273 | "is NOT supported\n"); | |
274 | } else { | |
275 | printf("Hardware transactional memory (lock elision) " | |
276 | "is supported\n"); | |
277 | ||
278 | printf("Test multi-writer with Hardware transactional memory\n"); | |
279 | ||
280 | use_htm = 1; | |
281 | if (test_hash_multiwriter() < 0) | |
282 | return -1; | |
283 | } | |
284 | ||
285 | printf("Test multi-writer without Hardware transactional memory\n"); | |
286 | use_htm = 0; | |
287 | if (test_hash_multiwriter() < 0) | |
288 | return -1; | |
289 | ||
290 | return 0; | |
291 | } | |
292 | ||
293 | REGISTER_TEST_COMMAND(hash_multiwriter_autotest, test_hash_multiwriter_main); |