Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2019 Mellanox Technologies, Ltd
3 : : */
4 : :
5 : : #include <eal_export.h>
6 : : #include <rte_malloc.h>
7 : : #include <rte_hash_crc.h>
8 : : #include <rte_errno.h>
9 : :
10 : : #include <mlx5_malloc.h>
11 : :
12 : : #include "mlx5_common_utils.h"
13 : : #include "mlx5_common_log.h"
14 : :
15 : : /********************* mlx5 list ************************/
16 : :
17 : : static int
18 : : mlx5_list_init(struct mlx5_list_inconst *l_inconst,
19 : : struct mlx5_list_const *l_const,
20 : : struct mlx5_list_cache *gc)
21 : : {
22 : : rte_rwlock_init(&l_inconst->lock);
23 [ # # # # ]: 0 : if (l_const->lcores_share) {
24 : 0 : l_inconst->cache[MLX5_LIST_GLOBAL] = gc;
25 : 0 : LIST_INIT(&l_inconst->cache[MLX5_LIST_GLOBAL]->h);
26 : : }
27 : : return 0;
28 : : }
29 : :
30 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_list_create)
31 : : struct mlx5_list *
32 : 0 : mlx5_list_create(const char *name, void *ctx, bool lcores_share,
33 : : mlx5_list_create_cb cb_create,
34 : : mlx5_list_match_cb cb_match,
35 : : mlx5_list_remove_cb cb_remove,
36 : : mlx5_list_clone_cb cb_clone,
37 : : mlx5_list_clone_free_cb cb_clone_free)
38 : : {
39 : : struct mlx5_list *list;
40 : : struct mlx5_list_cache *gc = NULL;
41 : :
42 [ # # # # : 0 : if (!cb_match || !cb_create || !cb_remove || !cb_clone ||
# # ]
43 : : !cb_clone_free) {
44 : 0 : rte_errno = EINVAL;
45 : 0 : return NULL;
46 : : }
47 [ # # ]: 0 : list = mlx5_malloc(MLX5_MEM_ZERO,
48 : : sizeof(*list) + (lcores_share ? sizeof(*gc) : 0),
49 : : 0, SOCKET_ID_ANY);
50 : :
51 [ # # ]: 0 : if (!list)
52 : : return NULL;
53 [ # # ]: 0 : if (name)
54 : 0 : snprintf(list->l_const.name,
55 : : sizeof(list->l_const.name), "%s", name);
56 : 0 : list->l_const.ctx = ctx;
57 : 0 : list->l_const.lcores_share = lcores_share;
58 : 0 : list->l_const.cb_create = cb_create;
59 : 0 : list->l_const.cb_match = cb_match;
60 : 0 : list->l_const.cb_remove = cb_remove;
61 : 0 : list->l_const.cb_clone = cb_clone;
62 [ # # ]: 0 : list->l_const.cb_clone_free = cb_clone_free;
63 : : rte_spinlock_init(&list->l_const.lcore_lock);
64 [ # # ]: 0 : if (lcores_share)
65 : 0 : gc = (struct mlx5_list_cache *)(list + 1);
66 : : if (mlx5_list_init(&list->l_inconst, &list->l_const, gc) != 0) {
67 : : mlx5_free(list);
68 : : return NULL;
69 : : }
70 : 0 : DRV_LOG(DEBUG, "mlx5 list %s was created.", name);
71 : 0 : return list;
72 : : }
73 : :
74 : : static struct mlx5_list_entry *
75 : 0 : __list_lookup(struct mlx5_list_inconst *l_inconst,
76 : : struct mlx5_list_const *l_const,
77 : : int lcore_index, void *ctx, bool reuse)
78 : : {
79 : 0 : struct mlx5_list_entry *entry =
80 : 0 : LIST_FIRST(&l_inconst->cache[lcore_index]->h);
81 : : uint32_t ret;
82 : :
83 [ # # ]: 0 : while (entry != NULL) {
84 [ # # ]: 0 : if (l_const->cb_match(l_const->ctx, entry, ctx) == 0) {
85 [ # # ]: 0 : if (reuse) {
86 : 0 : ret = rte_atomic_fetch_add_explicit(&entry->ref_cnt, 1,
87 : : rte_memory_order_relaxed);
88 : 0 : DRV_LOG(DEBUG, "mlx5 list %s entry %p ref: %u.",
89 : : l_const->name, (void *)entry,
90 : : entry->ref_cnt);
91 [ # # ]: 0 : } else if (lcore_index < MLX5_LIST_GLOBAL) {
92 : 0 : ret = rte_atomic_load_explicit(&entry->ref_cnt,
93 : : rte_memory_order_relaxed);
94 : : }
95 [ # # ]: 0 : if (likely(ret != 0 || lcore_index == MLX5_LIST_GLOBAL))
96 : 0 : return entry;
97 [ # # ]: 0 : if (reuse && ret == 0)
98 : 0 : entry->ref_cnt--; /* Invalid entry. */
99 : : }
100 : 0 : entry = LIST_NEXT(entry, next);
101 : : }
102 : : return NULL;
103 : : }
104 : :
105 : : static inline struct mlx5_list_entry *
106 : 0 : _mlx5_list_lookup(struct mlx5_list_inconst *l_inconst,
107 : : struct mlx5_list_const *l_const, void *ctx)
108 : : {
109 : : struct mlx5_list_entry *entry = NULL;
110 : : int i;
111 : :
112 : 0 : rte_rwlock_read_lock(&l_inconst->lock);
113 [ # # ]: 0 : for (i = 0; i < MLX5_LIST_GLOBAL; i++) {
114 [ # # ]: 0 : if (!l_inconst->cache[i])
115 : 0 : continue;
116 : 0 : entry = __list_lookup(l_inconst, l_const, i,
117 : : ctx, false);
118 [ # # ]: 0 : if (entry)
119 : : break;
120 : : }
121 : : rte_rwlock_read_unlock(&l_inconst->lock);
122 : 0 : return entry;
123 : : }
124 : :
125 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_list_lookup)
126 : : struct mlx5_list_entry *
127 : 0 : mlx5_list_lookup(struct mlx5_list *list, void *ctx)
128 : : {
129 : 0 : return _mlx5_list_lookup(&list->l_inconst, &list->l_const, ctx);
130 : : }
131 : :
132 : :
133 : : static struct mlx5_list_entry *
134 : 0 : mlx5_list_cache_insert(struct mlx5_list_inconst *l_inconst,
135 : : struct mlx5_list_const *l_const, int lcore_index,
136 : : struct mlx5_list_entry *gentry, void *ctx)
137 : : {
138 : : struct mlx5_list_entry *lentry =
139 : 0 : l_const->cb_clone(l_const->ctx, gentry, ctx);
140 : :
141 [ # # ]: 0 : if (unlikely(!lentry))
142 : : return NULL;
143 : 0 : lentry->ref_cnt = 1u;
144 : 0 : lentry->gentry = gentry;
145 : 0 : lentry->lcore_idx = (uint32_t)lcore_index;
146 [ # # ]: 0 : LIST_INSERT_HEAD(&l_inconst->cache[lcore_index]->h, lentry, next);
147 : 0 : return lentry;
148 : : }
149 : :
150 : : static void
151 : 0 : __list_cache_clean(struct mlx5_list_inconst *l_inconst,
152 : : struct mlx5_list_const *l_const,
153 : : int lcore_index)
154 : : {
155 : 0 : struct mlx5_list_cache *c = l_inconst->cache[lcore_index];
156 : 0 : struct mlx5_list_entry *entry = LIST_FIRST(&c->h);
157 : 0 : uint32_t inv_cnt = rte_atomic_exchange_explicit(&c->inv_cnt, 0,
158 : : rte_memory_order_relaxed);
159 : :
160 [ # # ]: 0 : while (inv_cnt != 0 && entry != NULL) {
161 : 0 : struct mlx5_list_entry *nentry = LIST_NEXT(entry, next);
162 : :
163 [ # # ]: 0 : if (rte_atomic_load_explicit(&entry->ref_cnt, rte_memory_order_relaxed) == 0) {
164 [ # # ]: 0 : LIST_REMOVE(entry, next);
165 [ # # ]: 0 : if (l_const->lcores_share)
166 : 0 : l_const->cb_clone_free(l_const->ctx, entry);
167 : : else
168 : 0 : l_const->cb_remove(l_const->ctx, entry);
169 : 0 : inv_cnt--;
170 : : }
171 : : entry = nentry;
172 : : }
173 : 0 : }
174 : :
175 : : static inline struct mlx5_list_entry *
176 : 0 : _mlx5_list_register(struct mlx5_list_inconst *l_inconst,
177 : : struct mlx5_list_const *l_const,
178 : : void *ctx, int lcore_index)
179 : : {
180 : : struct mlx5_list_entry *entry = NULL, *local_entry;
181 : 0 : volatile uint32_t prev_gen_cnt = 0;
182 : : MLX5_ASSERT(l_inconst);
183 [ # # ]: 0 : if (unlikely(!l_inconst->cache[lcore_index])) {
184 : 0 : l_inconst->cache[lcore_index] = mlx5_malloc(0,
185 : : sizeof(struct mlx5_list_cache),
186 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
187 [ # # ]: 0 : if (!l_inconst->cache[lcore_index]) {
188 : 0 : rte_errno = ENOMEM;
189 : 0 : return NULL;
190 : : }
191 : 0 : l_inconst->cache[lcore_index]->inv_cnt = 0;
192 : 0 : LIST_INIT(&l_inconst->cache[lcore_index]->h);
193 : : }
194 : : /* 0. Free entries that was invalidated by other lcores. */
195 : 0 : __list_cache_clean(l_inconst, l_const, lcore_index);
196 : : /* 1. Lookup in local cache. */
197 : 0 : local_entry = __list_lookup(l_inconst, l_const, lcore_index, ctx, true);
198 [ # # ]: 0 : if (local_entry)
199 : : return local_entry;
200 [ # # ]: 0 : if (l_const->lcores_share) {
201 : : /* 2. Lookup with read lock on global list, reuse if found. */
202 : 0 : rte_rwlock_read_lock(&l_inconst->lock);
203 : 0 : entry = __list_lookup(l_inconst, l_const, MLX5_LIST_GLOBAL,
204 : : ctx, true);
205 [ # # ]: 0 : if (likely(entry)) {
206 : : rte_rwlock_read_unlock(&l_inconst->lock);
207 : 0 : return mlx5_list_cache_insert(l_inconst, l_const,
208 : : lcore_index,
209 : : entry, ctx);
210 : : }
211 : 0 : prev_gen_cnt = l_inconst->gen_cnt;
212 : : rte_rwlock_read_unlock(&l_inconst->lock);
213 : : }
214 : : /* 3. Prepare new entry for global list and for cache. */
215 : 0 : entry = l_const->cb_create(l_const->ctx, ctx);
216 [ # # ]: 0 : if (unlikely(!entry))
217 : : return NULL;
218 : 0 : entry->ref_cnt = 1u;
219 [ # # ]: 0 : if (!l_const->lcores_share) {
220 : 0 : entry->lcore_idx = (uint32_t)lcore_index;
221 [ # # ]: 0 : LIST_INSERT_HEAD(&l_inconst->cache[lcore_index]->h,
222 : : entry, next);
223 : 0 : rte_atomic_fetch_add_explicit(&l_inconst->count, 1, rte_memory_order_relaxed);
224 : 0 : DRV_LOG(DEBUG, "MLX5 list %s c%d entry %p new: %u.",
225 : : l_const->name, lcore_index,
226 : : (void *)entry, entry->ref_cnt);
227 : 0 : return entry;
228 : : }
229 : 0 : local_entry = l_const->cb_clone(l_const->ctx, entry, ctx);
230 [ # # ]: 0 : if (unlikely(!local_entry)) {
231 : 0 : l_const->cb_remove(l_const->ctx, entry);
232 : 0 : return NULL;
233 : : }
234 : 0 : local_entry->ref_cnt = 1u;
235 : 0 : local_entry->gentry = entry;
236 : 0 : local_entry->lcore_idx = (uint32_t)lcore_index;
237 : 0 : rte_rwlock_write_lock(&l_inconst->lock);
238 : : /* 4. Make sure the same entry was not created before the write lock. */
239 [ # # ]: 0 : if (unlikely(prev_gen_cnt != l_inconst->gen_cnt)) {
240 : 0 : struct mlx5_list_entry *oentry = __list_lookup(l_inconst,
241 : : l_const,
242 : : MLX5_LIST_GLOBAL,
243 : : ctx, true);
244 : :
245 [ # # ]: 0 : if (unlikely(oentry)) {
246 : : /* 4.5. Found real race!!, reuse the old entry. */
247 : : rte_rwlock_write_unlock(&l_inconst->lock);
248 : 0 : l_const->cb_remove(l_const->ctx, entry);
249 : 0 : l_const->cb_clone_free(l_const->ctx, local_entry);
250 : 0 : return mlx5_list_cache_insert(l_inconst, l_const,
251 : : lcore_index,
252 : : oentry, ctx);
253 : : }
254 : : }
255 : : /* 5. Update lists. */
256 [ # # ]: 0 : LIST_INSERT_HEAD(&l_inconst->cache[MLX5_LIST_GLOBAL]->h, entry, next);
257 [ # # ]: 0 : l_inconst->gen_cnt++;
258 : : rte_rwlock_write_unlock(&l_inconst->lock);
259 [ # # ]: 0 : LIST_INSERT_HEAD(&l_inconst->cache[lcore_index]->h, local_entry, next);
260 : 0 : rte_atomic_fetch_add_explicit(&l_inconst->count, 1, rte_memory_order_relaxed);
261 : 0 : DRV_LOG(DEBUG, "mlx5 list %s entry %p new: %u.", l_const->name,
262 : : (void *)entry, entry->ref_cnt);
263 : 0 : return local_entry;
264 : : }
265 : :
266 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_list_register)
267 : : struct mlx5_list_entry *
268 : 0 : mlx5_list_register(struct mlx5_list *list, void *ctx)
269 : : {
270 : : struct mlx5_list_entry *entry;
271 : 0 : int lcore_index = rte_lcore_index(rte_lcore_id());
272 : :
273 [ # # ]: 0 : if (unlikely(lcore_index == -1)) {
274 : : lcore_index = MLX5_LIST_NLCORE;
275 : 0 : rte_spinlock_lock(&list->l_const.lcore_lock);
276 : : }
277 : 0 : entry = _mlx5_list_register(&list->l_inconst, &list->l_const, ctx,
278 : : lcore_index);
279 [ # # ]: 0 : if (unlikely(lcore_index == MLX5_LIST_NLCORE))
280 : 0 : rte_spinlock_unlock(&list->l_const.lcore_lock);
281 : 0 : return entry;
282 : : }
283 : :
284 : : static inline int
285 : 0 : _mlx5_list_unregister(struct mlx5_list_inconst *l_inconst,
286 : : struct mlx5_list_const *l_const,
287 : : struct mlx5_list_entry *entry,
288 : : int lcore_idx)
289 : : {
290 : 0 : struct mlx5_list_entry *gentry = entry->gentry;
291 : :
292 [ # # ]: 0 : if (rte_atomic_fetch_sub_explicit(&entry->ref_cnt, 1, rte_memory_order_relaxed) - 1 != 0)
293 : : return 1;
294 [ # # ]: 0 : if (entry->lcore_idx == (uint32_t)lcore_idx) {
295 [ # # ]: 0 : LIST_REMOVE(entry, next);
296 [ # # ]: 0 : if (l_const->lcores_share)
297 : 0 : l_const->cb_clone_free(l_const->ctx, entry);
298 : : else
299 : 0 : l_const->cb_remove(l_const->ctx, entry);
300 : : } else {
301 : 0 : rte_atomic_fetch_add_explicit(&l_inconst->cache[entry->lcore_idx]->inv_cnt,
302 : : 1, rte_memory_order_relaxed);
303 : : }
304 [ # # ]: 0 : if (!l_const->lcores_share) {
305 : 0 : rte_atomic_fetch_sub_explicit(&l_inconst->count, 1, rte_memory_order_relaxed);
306 : 0 : DRV_LOG(DEBUG, "mlx5 list %s entry %p removed.",
307 : : l_const->name, (void *)entry);
308 : 0 : return 0;
309 : : }
310 [ # # ]: 0 : if (rte_atomic_fetch_sub_explicit(&gentry->ref_cnt, 1, rte_memory_order_relaxed) - 1 != 0)
311 : : return 1;
312 : 0 : rte_rwlock_write_lock(&l_inconst->lock);
313 [ # # ]: 0 : if (likely(gentry->ref_cnt == 0)) {
314 [ # # ]: 0 : LIST_REMOVE(gentry, next);
315 : : rte_rwlock_write_unlock(&l_inconst->lock);
316 : 0 : l_const->cb_remove(l_const->ctx, gentry);
317 : 0 : rte_atomic_fetch_sub_explicit(&l_inconst->count, 1, rte_memory_order_relaxed);
318 : 0 : DRV_LOG(DEBUG, "mlx5 list %s entry %p removed.",
319 : : l_const->name, (void *)gentry);
320 : 0 : return 0;
321 : : }
322 : : rte_rwlock_write_unlock(&l_inconst->lock);
323 : 0 : return 1;
324 : : }
325 : :
326 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_list_unregister)
327 : : int
328 : 0 : mlx5_list_unregister(struct mlx5_list *list,
329 : : struct mlx5_list_entry *entry)
330 : : {
331 : : int ret;
332 : 0 : int lcore_index = rte_lcore_index(rte_lcore_id());
333 : :
334 [ # # ]: 0 : if (unlikely(lcore_index == -1)) {
335 : : lcore_index = MLX5_LIST_NLCORE;
336 : 0 : rte_spinlock_lock(&list->l_const.lcore_lock);
337 : : }
338 : 0 : ret = _mlx5_list_unregister(&list->l_inconst, &list->l_const, entry,
339 : : lcore_index);
340 [ # # ]: 0 : if (unlikely(lcore_index == MLX5_LIST_NLCORE))
341 : 0 : rte_spinlock_unlock(&list->l_const.lcore_lock);
342 : 0 : return ret;
343 : :
344 : : }
345 : :
346 : : static void
347 : 0 : mlx5_list_uninit(struct mlx5_list_inconst *l_inconst,
348 : : struct mlx5_list_const *l_const)
349 : : {
350 : : struct mlx5_list_entry *entry;
351 : : int i;
352 : :
353 : : MLX5_ASSERT(l_inconst);
354 [ # # ]: 0 : for (i = 0; i < MLX5_LIST_MAX; i++) {
355 [ # # ]: 0 : if (!l_inconst->cache[i])
356 : 0 : continue;
357 [ # # ]: 0 : while (!LIST_EMPTY(&l_inconst->cache[i]->h)) {
358 : : entry = LIST_FIRST(&l_inconst->cache[i]->h);
359 [ # # ]: 0 : LIST_REMOVE(entry, next);
360 [ # # ]: 0 : if (i == MLX5_LIST_GLOBAL) {
361 : 0 : l_const->cb_remove(l_const->ctx, entry);
362 : 0 : DRV_LOG(DEBUG, "mlx5 list %s entry %p "
363 : : "destroyed.", l_const->name,
364 : : (void *)entry);
365 : : } else {
366 : 0 : l_const->cb_clone_free(l_const->ctx, entry);
367 : : }
368 : : }
369 [ # # ]: 0 : if (i != MLX5_LIST_GLOBAL)
370 : 0 : mlx5_free(l_inconst->cache[i]);
371 : : }
372 : 0 : }
373 : :
374 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_list_destroy)
375 : : void
376 : 0 : mlx5_list_destroy(struct mlx5_list *list)
377 : : {
378 : 0 : mlx5_list_uninit(&list->l_inconst, &list->l_const);
379 : 0 : mlx5_free(list);
380 : 0 : }
381 : :
382 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_list_get_entry_num)
383 : : uint32_t
384 : 0 : mlx5_list_get_entry_num(struct mlx5_list *list)
385 : : {
386 : : MLX5_ASSERT(list);
387 : 0 : return rte_atomic_load_explicit(&list->l_inconst.count, rte_memory_order_relaxed);
388 : : }
389 : :
390 : : /********************* Hash List **********************/
391 : :
392 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_hlist_create)
393 : : struct mlx5_hlist *
394 : 0 : mlx5_hlist_create(const char *name, uint32_t size, bool direct_key,
395 : : bool lcores_share, void *ctx, mlx5_list_create_cb cb_create,
396 : : mlx5_list_match_cb cb_match,
397 : : mlx5_list_remove_cb cb_remove,
398 : : mlx5_list_clone_cb cb_clone,
399 : : mlx5_list_clone_free_cb cb_clone_free)
400 : : {
401 : : struct mlx5_hlist *h;
402 : : struct mlx5_list_cache *gc;
403 : : uint32_t act_size;
404 : : uint32_t alloc_size;
405 : : uint32_t i;
406 : :
407 [ # # # # : 0 : if (!cb_match || !cb_create || !cb_remove || !cb_clone ||
# # ]
408 : : !cb_clone_free) {
409 : 0 : rte_errno = EINVAL;
410 : 0 : return NULL;
411 : : }
412 : : /* Align to the next power of 2, 32bits integer is enough now. */
413 : : if (!rte_is_power_of_2(size)) {
414 : : act_size = rte_align32pow2(size);
415 : 0 : DRV_LOG(WARNING, "Size 0x%" PRIX32 " is not power of 2, will "
416 : : "be aligned to 0x%" PRIX32 ".", size, act_size);
417 : : } else {
418 : : act_size = size;
419 : : }
420 : 0 : alloc_size = sizeof(struct mlx5_hlist) +
421 : 0 : sizeof(struct mlx5_hlist_bucket) * act_size;
422 [ # # ]: 0 : if (lcores_share)
423 : 0 : alloc_size += sizeof(struct mlx5_list_cache) * act_size;
424 : : /* Using zmalloc, then no need to initialize the heads. */
425 : 0 : h = mlx5_malloc(MLX5_MEM_ZERO, alloc_size, RTE_CACHE_LINE_SIZE,
426 : : SOCKET_ID_ANY);
427 [ # # ]: 0 : if (!h) {
428 [ # # ]: 0 : DRV_LOG(ERR, "No memory for hash list %s creation",
429 : : name ? name : "None");
430 : 0 : return NULL;
431 : : }
432 [ # # ]: 0 : if (name)
433 : 0 : snprintf(h->l_const.name, sizeof(h->l_const.name), "%s", name);
434 : 0 : h->l_const.ctx = ctx;
435 : 0 : h->l_const.lcores_share = lcores_share;
436 : 0 : h->l_const.cb_create = cb_create;
437 : 0 : h->l_const.cb_match = cb_match;
438 : 0 : h->l_const.cb_remove = cb_remove;
439 : 0 : h->l_const.cb_clone = cb_clone;
440 : 0 : h->l_const.cb_clone_free = cb_clone_free;
441 : : rte_spinlock_init(&h->l_const.lcore_lock);
442 : 0 : h->mask = act_size - 1;
443 : 0 : h->direct_key = direct_key;
444 : 0 : gc = (struct mlx5_list_cache *)&h->buckets[act_size];
445 [ # # ]: 0 : for (i = 0; i < act_size; i++) {
446 [ # # # # ]: 0 : if (mlx5_list_init(&h->buckets[i].l, &h->l_const,
447 : 0 : lcores_share ? &gc[i] : NULL) != 0) {
448 : : mlx5_free(h);
449 : : return NULL;
450 : : }
451 : : }
452 : 0 : DRV_LOG(DEBUG, "Hash list %s with size 0x%" PRIX32 " was created.",
453 : : name, act_size);
454 : 0 : return h;
455 : : }
456 : :
457 : :
458 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_hlist_lookup)
459 : : struct mlx5_list_entry *
460 : 0 : mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key, void *ctx)
461 : : {
462 : : uint32_t idx;
463 : :
464 [ # # ]: 0 : if (h->direct_key)
465 : 0 : idx = (uint32_t)(key & h->mask);
466 : : else
467 : 0 : idx = rte_hash_crc_8byte(key, 0) & h->mask;
468 : 0 : return _mlx5_list_lookup(&h->buckets[idx].l, &h->l_const, ctx);
469 : : }
470 : :
471 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_hlist_register)
472 : : struct mlx5_list_entry*
473 : 0 : mlx5_hlist_register(struct mlx5_hlist *h, uint64_t key, void *ctx)
474 : : {
475 : : uint32_t idx;
476 : : struct mlx5_list_entry *entry;
477 : 0 : int lcore_index = rte_lcore_index(rte_lcore_id());
478 : :
479 [ # # ]: 0 : if (h->direct_key)
480 : 0 : idx = (uint32_t)(key & h->mask);
481 : : else
482 : 0 : idx = rte_hash_crc_8byte(key, 0) & h->mask;
483 [ # # ]: 0 : if (unlikely(lcore_index == -1)) {
484 : : lcore_index = MLX5_LIST_NLCORE;
485 : 0 : rte_spinlock_lock(&h->l_const.lcore_lock);
486 : : }
487 : 0 : entry = _mlx5_list_register(&h->buckets[idx].l, &h->l_const, ctx,
488 : : lcore_index);
489 [ # # ]: 0 : if (likely(entry)) {
490 [ # # ]: 0 : if (h->l_const.lcores_share)
491 : 0 : entry->gentry->bucket_idx = idx;
492 : : else
493 : 0 : entry->bucket_idx = idx;
494 : : }
495 [ # # ]: 0 : if (unlikely(lcore_index == MLX5_LIST_NLCORE))
496 : 0 : rte_spinlock_unlock(&h->l_const.lcore_lock);
497 : 0 : return entry;
498 : : }
499 : :
500 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_hlist_unregister)
501 : : int
502 : 0 : mlx5_hlist_unregister(struct mlx5_hlist *h, struct mlx5_list_entry *entry)
503 : : {
504 : 0 : int lcore_index = rte_lcore_index(rte_lcore_id());
505 : : int ret;
506 [ # # ]: 0 : uint32_t idx = h->l_const.lcores_share ? entry->gentry->bucket_idx :
507 : : entry->bucket_idx;
508 [ # # ]: 0 : if (unlikely(lcore_index == -1)) {
509 : : lcore_index = MLX5_LIST_NLCORE;
510 : 0 : rte_spinlock_lock(&h->l_const.lcore_lock);
511 : : }
512 : 0 : ret = _mlx5_list_unregister(&h->buckets[idx].l, &h->l_const, entry,
513 : : lcore_index);
514 [ # # ]: 0 : if (unlikely(lcore_index == MLX5_LIST_NLCORE))
515 : 0 : rte_spinlock_unlock(&h->l_const.lcore_lock);
516 : 0 : return ret;
517 : : }
518 : :
519 : : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_hlist_destroy)
520 : : void
521 : 0 : mlx5_hlist_destroy(struct mlx5_hlist *h)
522 : : {
523 : : uint32_t i;
524 : :
525 [ # # ]: 0 : for (i = 0; i <= h->mask; i++)
526 : 0 : mlx5_list_uninit(&h->buckets[i].l, &h->l_const);
527 : 0 : mlx5_free(h);
528 : 0 : }
|