Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : /**
6 : : * @file
7 : : * This file contains implementation of SORING 'datapath' functions.
8 : : *
9 : : * Brief description:
10 : : * ==================
11 : : * enqueue/dequeue works the same as for conventional rte_ring:
12 : : * any rte_ring sync types can be used, etc.
13 : : * Plus there could be multiple 'stages'.
14 : : * For each stage there is an acquire (start) and release (finish) operation.
15 : : * After some elems are 'acquired' - user can safely assume that he has
16 : : * exclusive possession of these elems till 'release' for them is done.
17 : : * Note that right now user has to release exactly the same number of elems
18 : : * he acquired before.
19 : : * After 'release', elems can be 'acquired' by next stage and/or dequeued
20 : : * (in case of last stage).
21 : : *
22 : : * Internal structure:
23 : : * ===================
24 : : * In addition to 'normal' ring of elems, it also has a ring of states of the
25 : : * same size. Each state[] corresponds to exactly one elem[].
26 : : * state[] will be used by acquire/release/dequeue functions to store internal
27 : : * information and should not be accessed by the user directly.
28 : : *
29 : : * How it works:
30 : : * =============
31 : : * 'acquire()' just moves stage's head (same as rte_ring move_head does),
32 : : * plus it saves in state[stage.cur_head] information about how many elems
33 : : * were acquired, current head position and special flag value to indicate
34 : : * that elems are acquired (SORING_ST_START).
35 : : * Note that 'acquire()' returns to the user a special 'ftoken' that user has
36 : : * to provide for 'release()' (in fact it is just a position for current head
37 : : * plus current stage index).
38 : : * 'release()' extracts old head value from provided ftoken and checks that
39 : : * corresponding 'state[]' contains expected values(mostly for sanity
40 : : * purposes).
41 : : * Then it marks this state[] with 'SORING_ST_FINISH' flag to indicate
42 : : * that given subset of objects was released.
43 : : * After that, it checks does old head value equals to current tail value?
44 : : * If yes, then it performs 'finalize()' operation, otherwise 'release()'
45 : : * just returns (without spinning on stage tail value).
46 : : * As updated state[] is shared by all threads, some other thread can do
47 : : * 'finalize()' for given stage.
48 : : * That allows 'release()' to avoid excessive waits on the tail value.
49 : : * Main purpose of 'finalize()' operation is to walk through 'state[]'
50 : : * from current stage tail up to its head, check state[] and move stage tail
51 : : * through elements that already are in SORING_ST_FINISH state.
52 : : * Along with that, corresponding state[] values are reset to zero.
53 : : * Note that 'finalize()' for given stage can be done from multiple places:
54 : : * 'release()' for that stage or from 'acquire()' for next stage
55 : : * even from consumer's 'dequeue()' - in case given stage is the last one.
56 : : * So 'finalize()' has to be MT-safe and inside it we have to
57 : : * guarantee that only one thread will update state[] and stage's tail values.
58 : : */
59 : :
60 : : #include "soring.h"
61 : :
62 : : #include <eal_export.h>
63 : :
64 : : /*
65 : : * Inline functions (fastpath) start here.
66 : : */
67 : : static __rte_always_inline uint32_t
68 : : __rte_soring_stage_finalize(struct soring_stage_headtail *sht, uint32_t stage,
69 : : union soring_state *rstate, uint32_t rmask, uint32_t maxn)
70 : : {
71 : : int32_t rc;
72 : : uint32_t ftkn, head, i, idx, k, n, tail;
73 : : union soring_stage_tail nt, ot;
74 : : union soring_state st;
75 : :
76 : : /* try to grab exclusive right to update tail value */
77 : 20010 : ot.raw = rte_atomic_load_explicit(&sht->tail.raw,
78 : : rte_memory_order_acquire);
79 : :
80 : : /* other thread already finalizing it for us */
81 : 20010 : if (ot.sync != 0)
82 : : return 0;
83 : :
84 : 20010 : nt.pos = ot.pos;
85 : 20010 : nt.sync = 1;
86 : 20010 : rc = rte_atomic_compare_exchange_strong_explicit(&sht->tail.raw,
87 : : (uint64_t *)(uintptr_t)&ot.raw, nt.raw,
88 : : rte_memory_order_release, rte_memory_order_relaxed);
89 : :
90 : : /* other thread won the race */
91 [ + - + - : 20010 : if (rc == 0)
- - - - -
- - - - -
+ - - - +
- ]
92 : : return 0;
93 : :
94 : : /* Ensure the head is read before rstate[] */
95 : 20010 : head = rte_atomic_load_explicit(&sht->head, rte_memory_order_relaxed);
96 : : rte_atomic_thread_fence(rte_memory_order_acquire);
97 : :
98 : : /*
99 : : * start with current tail and walk through states that are
100 : : * already finished.
101 : : */
102 : :
103 : 20010 : n = RTE_MIN(head - ot.pos, maxn);
104 [ + + + + : 30015 : for (i = 0, tail = ot.pos; i < n; i += k, tail += k) {
- - - - -
- - - - -
- + - - -
+ ]
105 : :
106 : 10005 : idx = tail & rmask;
107 : 10005 : ftkn = SORING_FTKN_MAKE(tail, stage);
108 : :
109 : 10005 : st.raw = rte_atomic_load_explicit(&rstate[idx].raw,
110 : : rte_memory_order_relaxed);
111 [ + - + - : 10005 : if ((st.stnum & SORING_ST_MASK) != SORING_ST_FINISH ||
+ - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- ]
112 : : st.ftoken != ftkn)
113 : : break;
114 : :
115 : 10005 : k = st.stnum & ~SORING_ST_MASK;
116 : 10005 : rte_atomic_store_explicit(&rstate[idx].raw, 0,
117 : : rte_memory_order_relaxed);
118 : : }
119 : :
120 : :
121 : : /* release exclusive right to update along with new tail value */
122 : 20010 : ot.pos = tail;
123 : 20010 : rte_atomic_store_explicit(&sht->tail.raw, ot.raw,
124 : : rte_memory_order_release);
125 : :
126 : 20010 : return i;
127 : : }
128 : :
129 : : static __rte_always_inline uint32_t
130 : : __rte_soring_move_prod_head(struct rte_soring *r, uint32_t num,
131 : : enum rte_ring_queue_behavior behavior, enum rte_ring_sync_type st,
132 : : uint32_t *head, uint32_t *next, uint32_t *free)
133 : : {
134 : : uint32_t n;
135 : :
136 : 6 : switch (st) {
137 : 6 : case RTE_RING_SYNC_ST:
138 : : case RTE_RING_SYNC_MT:
139 : 6 : n = __rte_ring_headtail_move_head(&r->prod.ht, &r->cons.ht,
140 : : r->capacity, st, num, behavior, head, next, free);
141 : : break;
142 : 0 : case RTE_RING_SYNC_MT_RTS:
143 : 0 : n = __rte_ring_rts_move_head(&r->prod.rts, &r->cons.ht,
144 : : r->capacity, num, behavior, head, free);
145 : 0 : *next = *head + n;
146 : 0 : break;
147 : 0 : case RTE_RING_SYNC_MT_HTS:
148 : 0 : n = __rte_ring_hts_move_head(&r->prod.hts, &r->cons.ht,
149 : : r->capacity, num, behavior, head, free);
150 : 0 : *next = *head + n;
151 : 0 : break;
152 : : default:
153 : : /* unsupported mode, shouldn't be here */
154 : : RTE_ASSERT(0);
155 : : *free = 0;
156 : : n = 0;
157 : : }
158 : :
159 : : return n;
160 : : }
161 : :
162 : : static __rte_always_inline uint32_t
163 : : __rte_soring_move_cons_head(struct rte_soring *r, uint32_t stage, uint32_t num,
164 : : enum rte_ring_queue_behavior behavior, enum rte_ring_sync_type st,
165 : : uint32_t *head, uint32_t *next, uint32_t *avail)
166 : : {
167 : : uint32_t n;
168 : :
169 [ - - - - : 3 : switch (st) {
+ - - - -
- - - - -
- - ]
170 : 10011 : case RTE_RING_SYNC_ST:
171 : : case RTE_RING_SYNC_MT:
172 : : n = __rte_ring_headtail_move_head(&r->cons.ht,
173 : 10011 : &r->stage[stage].ht, 0, st, num, behavior,
174 : : head, next, avail);
175 : : break;
176 : 0 : case RTE_RING_SYNC_MT_RTS:
177 : 0 : n = __rte_ring_rts_move_head(&r->cons.rts, &r->stage[stage].ht,
178 : : 0, num, behavior, head, avail);
179 : 0 : *next = *head + n;
180 : 0 : break;
181 : 0 : case RTE_RING_SYNC_MT_HTS:
182 : 0 : n = __rte_ring_hts_move_head(&r->cons.hts, &r->stage[stage].ht,
183 : : 0, num, behavior, head, avail);
184 : 0 : *next = *head + n;
185 : 0 : break;
186 : : default:
187 : : /* unsupported mode, shouldn't be here */
188 : : RTE_ASSERT(0);
189 : : *avail = 0;
190 : : n = 0;
191 : : }
192 : :
193 : : return n;
194 : : }
195 : :
196 : : static __rte_always_inline void
197 : : __rte_soring_update_tail(struct __rte_ring_headtail *rht,
198 : : enum rte_ring_sync_type st, uint32_t head, uint32_t next, uint32_t enq)
199 : : {
200 : : uint32_t n;
201 : :
202 [ + - - - : 9 : switch (st) {
+ - - - +
- - - - -
- - + - -
- + - - -
- - - - -
- - - ]
203 : : case RTE_RING_SYNC_ST:
204 : : case RTE_RING_SYNC_MT:
205 : : __rte_ring_update_tail(&rht->ht, head, next, st, enq);
206 : : break;
207 : 0 : case RTE_RING_SYNC_MT_RTS:
208 : : __rte_ring_rts_update_tail(&rht->rts);
209 : : break;
210 : 0 : case RTE_RING_SYNC_MT_HTS:
211 : : n = next - head;
212 : : __rte_ring_hts_update_tail(&rht->hts, head, n, enq);
213 : : break;
214 : : default:
215 : : /* unsupported mode, shouldn't be here */
216 : : RTE_ASSERT(0);
217 : : }
218 : : }
219 : :
220 : : static __rte_always_inline uint32_t
221 : : __rte_soring_stage_move_head(struct soring_stage_headtail *d,
222 : : const struct rte_ring_headtail *s, uint32_t capacity, uint32_t num,
223 : : enum rte_ring_queue_behavior behavior,
224 : : uint32_t *old_head, uint32_t *new_head, uint32_t *avail)
225 : : {
226 : : uint32_t n, tail;
227 : :
228 : 5 : *old_head = rte_atomic_load_explicit(&d->head,
229 : : rte_memory_order_relaxed);
230 : :
231 : : do {
232 : : n = num;
233 : :
234 : : /* Ensure the head is read before tail */
235 : : rte_atomic_thread_fence(rte_memory_order_acquire);
236 : :
237 : 10005 : tail = rte_atomic_load_explicit(&s->tail,
238 : : rte_memory_order_acquire);
239 : 10005 : *avail = capacity + tail - *old_head;
240 [ + - - - : 10003 : if (n > *avail)
+ - + - -
- + - - -
- - ]
241 : : n = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : *avail;
242 [ + - + - : 10005 : if (n == 0)
- - - - -
- - - + -
+ - - - +
- - - -
- ]
243 : : return 0;
244 : 10005 : *new_head = *old_head + n;
245 : 10005 : } while (rte_atomic_compare_exchange_strong_explicit(&d->head,
246 : : old_head, *new_head, rte_memory_order_acq_rel,
247 [ - + - + : 10005 : rte_memory_order_relaxed) == 0);
- - - - -
- - - - +
- + - - -
+ - - -
- ]
248 : :
249 : : return n;
250 : : }
251 : :
252 : : static __rte_always_inline uint32_t
253 : : soring_enqueue(struct rte_soring *r, const void *objs,
254 : : const void *meta, uint32_t n, enum rte_ring_queue_behavior behavior,
255 : : uint32_t *free_space)
256 : : {
257 : : enum rte_ring_sync_type st;
258 : : uint32_t nb_free, prod_head, prod_next;
259 : :
260 : : RTE_ASSERT(r != NULL && r->nb_stage > 0);
261 : : RTE_ASSERT(meta == NULL || r->meta != NULL);
262 : :
263 : 6 : st = r->prod.ht.sync_type;
264 : :
265 : : n = __rte_soring_move_prod_head(r, n, behavior, st,
266 : : &prod_head, &prod_next, &nb_free);
267 [ + - + - : 6 : if (n != 0) {
- - - + ]
268 : 5 : __rte_ring_do_enqueue_elems(&r[1], objs, r->size,
269 [ - + + + : 5 : prod_head & r->mask, r->esize, n);
- - - - ]
270 [ + - - - ]: 2 : if (meta != NULL)
271 : 2 : __rte_ring_do_enqueue_elems(r->meta, meta, r->size,
272 [ - + - - ]: 2 : prod_head & r->mask, r->msize, n);
273 : : __rte_soring_update_tail(&r->prod, st, prod_head, prod_next, 1);
274 : : }
275 : :
276 [ + + + - : 6 : if (free_space != NULL)
- - + - ]
277 : 5 : *free_space = nb_free - n;
278 : : return n;
279 : : }
280 : :
281 : : static __rte_always_inline uint32_t
282 : : soring_dequeue(struct rte_soring *r, void *objs, void *meta,
283 : : uint32_t num, enum rte_ring_queue_behavior behavior,
284 : : uint32_t *available)
285 : : {
286 : : enum rte_ring_sync_type st;
287 : : uint32_t entries, cons_head, cons_next, n, ns, reqn;
288 : :
289 : : RTE_ASSERT(r != NULL && r->nb_stage > 0);
290 : : RTE_ASSERT(meta == NULL || r->meta != NULL);
291 : :
292 : 10008 : ns = r->nb_stage - 1;
293 : 10008 : st = r->cons.ht.sync_type;
294 : :
295 : : /* try to grab exactly @num elems first */
296 : : n = __rte_soring_move_cons_head(r, ns, num, RTE_RING_QUEUE_FIXED, st,
297 : : &cons_head, &cons_next, &entries);
298 [ - + + + : 10008 : if (n == 0) {
- + + - ]
299 : : /* try to finalize some elems from previous stage */
300 [ - - + - : 10005 : n = __rte_soring_stage_finalize(&r->stage[ns].sht, ns,
- - + - ]
301 : : r->state, r->mask, 2 * num);
302 : 10002 : entries += n;
303 : :
304 : : /* repeat attempt to grab elems */
305 : : reqn = (behavior == RTE_RING_QUEUE_FIXED) ? num : 0;
306 [ - - - + ]: 10002 : if (entries >= reqn)
307 : : n = __rte_soring_move_cons_head(r, ns, num, behavior,
308 : : st, &cons_head, &cons_next, &entries);
309 : : else
310 : : n = 0;
311 : : }
312 : :
313 : : /* we have some elems to consume */
314 [ + - + + : 10008 : if (n != 0) {
+ - - + ]
315 : 4 : __rte_ring_do_dequeue_elems(objs, &r[1], r->size,
316 [ - + + - : 4 : cons_head & r->mask, r->esize, n);
- + - - ]
317 [ + - + - ]: 2 : if (meta != NULL)
318 : 2 : __rte_ring_do_dequeue_elems(meta, r->meta, r->size,
319 [ - + - + ]: 2 : cons_head & r->mask, r->msize, n);
320 : : __rte_soring_update_tail(&r->cons, st, cons_head, cons_next, 0);
321 : : }
322 : :
323 [ - + - + : 10008 : if (available != NULL)
- + - + ]
324 : 0 : *available = entries - n;
325 : : return n;
326 : : }
327 : :
328 : : /*
329 : : * Verify internal SORING state.
330 : : * WARNING: if expected value is not equal to actual one, it means that for
331 : : * whatever reason SORING data constancy is broken. That is a very serious
332 : : * problem that most likely will cause race-conditions, memory corruption,
333 : : * program crash.
334 : : * To ease debugging it user might rebuild ring library with
335 : : * RTE_SORING_DEBUG enabled.
336 : : */
337 : : static __rte_always_inline void
338 : : soring_verify_state(const struct rte_soring *r, uint32_t stage, uint32_t idx,
339 : : const char *msg, union soring_state val, union soring_state exp)
340 : : {
341 : 20010 : if (val.raw != exp.raw) {
342 : : #ifdef RTE_SORING_DEBUG
343 : : rte_soring_dump(stderr, r);
344 : : rte_panic("line:%d from:%s: soring=%p, stage=%#x, idx=%#x, "
345 : : "expected={.stnum=%#x, .ftoken=%#x}, "
346 : : "actual={.stnum=%#x, .ftoken=%#x};\n",
347 : : __LINE__, msg, r, stage, idx,
348 : : exp.stnum, exp.ftoken,
349 : : val.stnum, val.ftoken);
350 : : #else
351 : 0 : SORING_LOG(EMERG, "from:%s: soring=%p, stage=%#x, idx=%#x, "
352 : : "expected={.stnum=%#x, .ftoken=%#x}, "
353 : : "actual={.stnum=%#x, .ftoken=%#x};",
354 : : msg, r, stage, idx,
355 : : exp.stnum, exp.ftoken,
356 : : val.stnum, val.ftoken);
357 : : #endif
358 : : }
359 : : }
360 : :
361 : : /* check and update state ring at acquire op*/
362 : : static __rte_always_inline void
363 : : acquire_state_update(const struct rte_soring *r, uint32_t stage, uint32_t idx,
364 : : uint32_t ftoken, uint32_t num)
365 : : {
366 : : union soring_state st;
367 : : const union soring_state est = {.raw = 0};
368 : :
369 : 10005 : st.raw = rte_atomic_load_explicit(&r->state[idx].raw,
370 : : rte_memory_order_relaxed);
371 : : soring_verify_state(r, stage, idx, __func__, st, est);
372 : :
373 : 10005 : st.ftoken = ftoken;
374 : 10005 : st.stnum = (SORING_ST_START | num);
375 : :
376 : 10005 : rte_atomic_store_explicit(&r->state[idx].raw, st.raw,
377 : : rte_memory_order_relaxed);
378 : : }
379 : :
380 : : static __rte_always_inline uint32_t
381 : : soring_acquire(struct rte_soring *r, void *objs, void *meta,
382 : : uint32_t stage, uint32_t num, enum rte_ring_queue_behavior behavior,
383 : : uint32_t *ftoken, uint32_t *available)
384 : : {
385 : : uint32_t avail, head, idx, n, next, reqn;
386 : : struct soring_stage *pstg;
387 : : struct soring_stage_headtail *cons;
388 : :
389 : : RTE_ASSERT(r != NULL && stage < r->nb_stage);
390 : : RTE_ASSERT(meta == NULL || r->meta != NULL);
391 : :
392 : 10005 : cons = &r->stage[stage].sht;
393 : :
394 : 10005 : if (stage == 0)
395 : : n = __rte_soring_stage_move_head(cons, &r->prod.ht, 0, num,
396 : : behavior, &head, &next, &avail);
397 : : else {
398 : 10000 : pstg = r->stage + stage - 1;
399 : :
400 : : /* try to grab exactly @num elems */
401 : : n = __rte_soring_stage_move_head(cons, &pstg->ht, 0, num,
402 : : RTE_RING_QUEUE_FIXED, &head, &next, &avail);
403 [ - + - - : 10000 : if (n == 0) {
- + - - ]
404 : : /* try to finalize some elems from previous stage */
405 [ # # # # : 0 : n = __rte_soring_stage_finalize(&pstg->sht, stage - 1,
# # # # ]
406 : : r->state, r->mask, 2 * num);
407 : 0 : avail += n;
408 : :
409 : : /* repeat attempt to grab elems */
410 : : reqn = (behavior == RTE_RING_QUEUE_FIXED) ? num : 0;
411 [ # # # # ]: 0 : if (avail >= reqn)
412 : : n = __rte_soring_stage_move_head(cons,
413 : : &pstg->ht, 0, num, behavior, &head,
414 : : &next, &avail);
415 : : else
416 : : n = 0;
417 : : }
418 : : }
419 : :
420 [ + - - - : 10005 : if (n != 0) {
+ - + - ]
421 : :
422 : 10005 : idx = head & r->mask;
423 [ - + - - : 10005 : *ftoken = SORING_FTKN_MAKE(head, stage);
- + - + ]
424 : :
425 : : /* check and update state value */
426 : : acquire_state_update(r, stage, idx, *ftoken, n);
427 : :
428 : : /* copy elems that are ready for given stage */
429 [ - + - - : 10005 : __rte_ring_do_dequeue_elems(objs, &r[1], r->size, idx,
- + + - ]
430 : : r->esize, n);
431 [ + - + - ]: 10003 : if (meta != NULL)
432 [ - + - + ]: 10003 : __rte_ring_do_dequeue_elems(meta, r->meta,
433 : : r->size, idx, r->msize, n);
434 : : }
435 : :
436 [ - + - - : 10005 : if (available != NULL)
- + - + ]
437 : 0 : *available = avail - n;
438 : : return n;
439 : : }
440 : :
441 : : static __rte_always_inline void
442 : : soring_release(struct rte_soring *r, const void *objs,
443 : : const void *meta, uint32_t stage, uint32_t n, uint32_t ftoken)
444 : : {
445 : : uint32_t idx, pos, tail;
446 : : struct soring_stage *stg;
447 : : union soring_state st;
448 : :
449 : : const union soring_state est = {
450 : 10005 : .stnum = (SORING_ST_START | n),
451 : : .ftoken = ftoken,
452 : : };
453 : :
454 : : RTE_ASSERT(r != NULL && stage < r->nb_stage);
455 : : RTE_ASSERT(meta == NULL || r->meta != NULL);
456 : :
457 : 10005 : stg = r->stage + stage;
458 : :
459 : 10005 : pos = SORING_FTKN_POS(ftoken, stage);
460 : 10005 : idx = pos & r->mask;
461 : 10005 : st.raw = rte_atomic_load_explicit(&r->state[idx].raw,
462 : : rte_memory_order_relaxed);
463 : :
464 : : /* check state ring contents */
465 : 10005 : soring_verify_state(r, stage, idx, __func__, st, est);
466 : :
467 : : /* update contents of the ring, if necessary */
468 [ + + - + ]: 10005 : if (objs != NULL)
469 [ - + - - ]: 10000 : __rte_ring_do_enqueue_elems(&r[1], objs, r->size, idx,
470 : : r->esize, n);
471 [ + - ]: 10001 : if (meta != NULL)
472 [ - + ]: 10001 : __rte_ring_do_enqueue_elems(r->meta, meta, r->size, idx,
473 : : r->msize, n);
474 : :
475 : : /* set state to FINISH, make sure it is not reordered */
476 : : rte_atomic_thread_fence(rte_memory_order_release);
477 : :
478 : 10005 : st.stnum = SORING_ST_FINISH | n;
479 : 10005 : rte_atomic_store_explicit(&r->state[idx].raw, st.raw,
480 : : rte_memory_order_relaxed);
481 : :
482 : : /* try to do finalize(), if appropriate */
483 : 10005 : tail = rte_atomic_load_explicit(&stg->sht.tail.pos,
484 : : rte_memory_order_relaxed);
485 [ + - + - ]: 10005 : if (tail == pos)
486 [ + - + - ]: 10005 : __rte_soring_stage_finalize(&stg->sht, stage, r->state, r->mask,
487 : : r->capacity);
488 : : }
489 : :
490 : : /*
491 : : * Public functions (data-path) start here.
492 : : */
493 : :
494 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_release, 25.03)
495 : : void
496 [ - + ]: 4 : rte_soring_release(struct rte_soring *r, const void *objs,
497 : : uint32_t stage, uint32_t n, uint32_t ftoken)
498 : : {
499 : : soring_release(r, objs, NULL, stage, n, ftoken);
500 : 4 : }
501 : :
502 : :
503 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_releasx, 25.03)
504 : : void
505 [ - + ]: 10001 : rte_soring_releasx(struct rte_soring *r, const void *objs,
506 : : const void *meta, uint32_t stage, uint32_t n, uint32_t ftoken)
507 : : {
508 : : soring_release(r, objs, meta, stage, n, ftoken);
509 : 10001 : }
510 : :
511 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_enqueue_bulk, 25.03)
512 : : uint32_t
513 [ + - - - ]: 1 : rte_soring_enqueue_bulk(struct rte_soring *r, const void *objs, uint32_t n,
514 : : uint32_t *free_space)
515 : : {
516 : 1 : return soring_enqueue(r, objs, NULL, n, RTE_RING_QUEUE_FIXED,
517 : : free_space);
518 : : }
519 : :
520 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_enqueux_bulk, 25.03)
521 : : uint32_t
522 [ # # # # ]: 0 : rte_soring_enqueux_bulk(struct rte_soring *r, const void *objs,
523 : : const void *meta, uint32_t n, uint32_t *free_space)
524 : : {
525 : 0 : return soring_enqueue(r, objs, meta, n, RTE_RING_QUEUE_FIXED,
526 : : free_space);
527 : : }
528 : :
529 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_enqueue_burst, 25.03)
530 : : uint32_t
531 [ + - - - ]: 3 : rte_soring_enqueue_burst(struct rte_soring *r, const void *objs, uint32_t n,
532 : : uint32_t *free_space)
533 : : {
534 : 3 : return soring_enqueue(r, objs, NULL, n, RTE_RING_QUEUE_VARIABLE,
535 : : free_space);
536 : : }
537 : :
538 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_enqueux_burst, 25.03)
539 : : uint32_t
540 [ + - - - ]: 2 : rte_soring_enqueux_burst(struct rte_soring *r, const void *objs,
541 : : const void *meta, uint32_t n, uint32_t *free_space)
542 : : {
543 : 2 : return soring_enqueue(r, objs, meta, n, RTE_RING_QUEUE_VARIABLE,
544 : : free_space);
545 : : }
546 : :
547 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_dequeue_bulk, 25.03)
548 : : uint32_t
549 [ + - - - ]: 10002 : rte_soring_dequeue_bulk(struct rte_soring *r, void *objs, uint32_t num,
550 : : uint32_t *available)
551 : : {
552 : 10002 : return soring_dequeue(r, objs, NULL, num, RTE_RING_QUEUE_FIXED,
553 : : available);
554 : : }
555 : :
556 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_dequeux_bulk, 25.03)
557 : : uint32_t
558 [ + - - - ]: 1 : rte_soring_dequeux_bulk(struct rte_soring *r, void *objs, void *meta,
559 : : uint32_t num, uint32_t *available)
560 : : {
561 : 1 : return soring_dequeue(r, objs, meta, num, RTE_RING_QUEUE_FIXED,
562 : : available);
563 : : }
564 : :
565 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_dequeue_burst, 25.03)
566 : : uint32_t
567 [ + - - - ]: 4 : rte_soring_dequeue_burst(struct rte_soring *r, void *objs, uint32_t num,
568 : : uint32_t *available)
569 : : {
570 : 4 : return soring_dequeue(r, objs, NULL, num, RTE_RING_QUEUE_VARIABLE,
571 : : available);
572 : : }
573 : :
574 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_dequeux_burst, 25.03)
575 : : uint32_t
576 [ + - - - ]: 1 : rte_soring_dequeux_burst(struct rte_soring *r, void *objs, void *meta,
577 : : uint32_t num, uint32_t *available)
578 : : {
579 : 1 : return soring_dequeue(r, objs, meta, num, RTE_RING_QUEUE_VARIABLE,
580 : : available);
581 : : }
582 : :
583 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_acquire_bulk, 25.03)
584 : : uint32_t
585 [ + - ]: 2 : rte_soring_acquire_bulk(struct rte_soring *r, void *objs,
586 : : uint32_t stage, uint32_t num, uint32_t *ftoken, uint32_t *available)
587 : : {
588 : 2 : return soring_acquire(r, objs, NULL, stage, num,
589 : : RTE_RING_QUEUE_FIXED, ftoken, available);
590 : : }
591 : :
592 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_acquirx_bulk, 25.03)
593 : : uint32_t
594 [ + + ]: 10000 : rte_soring_acquirx_bulk(struct rte_soring *r, void *objs, void *meta,
595 : : uint32_t stage, uint32_t num, uint32_t *ftoken, uint32_t *available)
596 : : {
597 : 10000 : return soring_acquire(r, objs, meta, stage, num,
598 : : RTE_RING_QUEUE_FIXED, ftoken, available);
599 : : }
600 : :
601 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_acquire_burst, 25.03)
602 : : uint32_t
603 [ # # ]: 0 : rte_soring_acquire_burst(struct rte_soring *r, void *objs,
604 : : uint32_t stage, uint32_t num, uint32_t *ftoken, uint32_t *available)
605 : : {
606 : 0 : return soring_acquire(r, objs, NULL, stage, num,
607 : : RTE_RING_QUEUE_VARIABLE, ftoken, available);
608 : : }
609 : :
610 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_acquirx_burst, 25.03)
611 : : uint32_t
612 [ + + ]: 3 : rte_soring_acquirx_burst(struct rte_soring *r, void *objs, void *meta,
613 : : uint32_t stage, uint32_t num, uint32_t *ftoken, uint32_t *available)
614 : : {
615 : 3 : return soring_acquire(r, objs, meta, stage, num,
616 : : RTE_RING_QUEUE_VARIABLE, ftoken, available);
617 : : }
618 : :
619 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_count, 25.03)
620 : : unsigned int
621 : 4 : rte_soring_count(const struct rte_soring *r)
622 : : {
623 : 4 : uint32_t prod_tail = r->prod.ht.tail;
624 : 4 : uint32_t cons_tail = r->cons.ht.tail;
625 : 4 : uint32_t count = (prod_tail - cons_tail) & r->mask;
626 : 4 : return (count > r->capacity) ? r->capacity : count;
627 : : }
628 : :
629 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_soring_free_count, 25.03)
630 : : unsigned int
631 : 2 : rte_soring_free_count(const struct rte_soring *r)
632 : : {
633 : 2 : return r->capacity - rte_soring_count(r);
634 : : }
|