xref: /dpdk/lib/ring/rte_ring_hts.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  *
399a2dd95SBruce Richardson  * Copyright (c) 2010-2020 Intel Corporation
499a2dd95SBruce Richardson  * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
599a2dd95SBruce Richardson  * All rights reserved.
699a2dd95SBruce Richardson  * Derived from FreeBSD's bufring.h
799a2dd95SBruce Richardson  * Used as BSD-3 Licensed with permission from Kip Macy.
899a2dd95SBruce Richardson  */
999a2dd95SBruce Richardson 
1099a2dd95SBruce Richardson #ifndef _RTE_RING_HTS_H_
1199a2dd95SBruce Richardson #define _RTE_RING_HTS_H_
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson /**
1499a2dd95SBruce Richardson  * @file rte_ring_hts.h
1599a2dd95SBruce Richardson  * It is not recommended to include this file directly.
1699a2dd95SBruce Richardson  * Please include <rte_ring.h> instead.
1799a2dd95SBruce Richardson  *
1899a2dd95SBruce Richardson  * Contains functions for serialized, aka Head-Tail Sync (HTS) ring mode.
1999a2dd95SBruce Richardson  * In that mode enqueue/dequeue operation is fully serialized:
2099a2dd95SBruce Richardson  * at any given moment only one enqueue/dequeue operation can proceed.
2199a2dd95SBruce Richardson  * This is achieved by allowing a thread to proceed with changing head.value
2299a2dd95SBruce Richardson  * only when head.value == tail.value.
2399a2dd95SBruce Richardson  * Both head and tail values are updated atomically (as one 64-bit value).
2499a2dd95SBruce Richardson  * To achieve that 64-bit CAS is used by head update routine.
2599a2dd95SBruce Richardson  */
2699a2dd95SBruce Richardson 
27*719834a6SMattias Rönnblom #include <rte_ring_hts_elem_pvt.h>
28*719834a6SMattias Rönnblom 
2999a2dd95SBruce Richardson #ifdef __cplusplus
3099a2dd95SBruce Richardson extern "C" {
3199a2dd95SBruce Richardson #endif
3299a2dd95SBruce Richardson 
3399a2dd95SBruce Richardson /**
3499a2dd95SBruce Richardson  * Enqueue several objects on the HTS ring (multi-producers safe).
3599a2dd95SBruce Richardson  *
3699a2dd95SBruce Richardson  * @param r
3799a2dd95SBruce Richardson  *   A pointer to the ring structure.
3899a2dd95SBruce Richardson  * @param obj_table
3999a2dd95SBruce Richardson  *   A pointer to a table of objects.
4099a2dd95SBruce Richardson  * @param esize
4199a2dd95SBruce Richardson  *   The size of ring element, in bytes. It must be a multiple of 4.
4299a2dd95SBruce Richardson  *   This must be the same value used while creating the ring. Otherwise
4399a2dd95SBruce Richardson  *   the results are undefined.
4499a2dd95SBruce Richardson  * @param n
4599a2dd95SBruce Richardson  *   The number of objects to add in the ring from the obj_table.
4699a2dd95SBruce Richardson  * @param free_space
4799a2dd95SBruce Richardson  *   if non-NULL, returns the amount of space in the ring after the
4899a2dd95SBruce Richardson  *   enqueue operation has finished.
4999a2dd95SBruce Richardson  * @return
5099a2dd95SBruce Richardson  *   The number of objects enqueued, either 0 or n
5199a2dd95SBruce Richardson  */
5299a2dd95SBruce Richardson static __rte_always_inline unsigned int
5399a2dd95SBruce Richardson rte_ring_mp_hts_enqueue_bulk_elem(struct rte_ring *r, const void *obj_table,
5499a2dd95SBruce Richardson 	unsigned int esize, unsigned int n, unsigned int *free_space)
5599a2dd95SBruce Richardson {
5699a2dd95SBruce Richardson 	return __rte_ring_do_hts_enqueue_elem(r, obj_table, esize, n,
5799a2dd95SBruce Richardson 			RTE_RING_QUEUE_FIXED, free_space);
5899a2dd95SBruce Richardson }
5999a2dd95SBruce Richardson 
6099a2dd95SBruce Richardson /**
6199a2dd95SBruce Richardson  * Dequeue several objects from an HTS ring (multi-consumers safe).
6299a2dd95SBruce Richardson  *
6399a2dd95SBruce Richardson  * @param r
6499a2dd95SBruce Richardson  *   A pointer to the ring structure.
6599a2dd95SBruce Richardson  * @param obj_table
6699a2dd95SBruce Richardson  *   A pointer to a table of objects that will be filled.
6799a2dd95SBruce Richardson  * @param esize
6899a2dd95SBruce Richardson  *   The size of ring element, in bytes. It must be a multiple of 4.
6999a2dd95SBruce Richardson  *   This must be the same value used while creating the ring. Otherwise
7099a2dd95SBruce Richardson  *   the results are undefined.
7199a2dd95SBruce Richardson  * @param n
7299a2dd95SBruce Richardson  *   The number of objects to dequeue from the ring to the obj_table.
7399a2dd95SBruce Richardson  * @param available
7499a2dd95SBruce Richardson  *   If non-NULL, returns the number of remaining ring entries after the
7599a2dd95SBruce Richardson  *   dequeue has finished.
7699a2dd95SBruce Richardson  * @return
7799a2dd95SBruce Richardson  *   The number of objects dequeued, either 0 or n
7899a2dd95SBruce Richardson  */
7999a2dd95SBruce Richardson static __rte_always_inline unsigned int
8099a2dd95SBruce Richardson rte_ring_mc_hts_dequeue_bulk_elem(struct rte_ring *r, void *obj_table,
8199a2dd95SBruce Richardson 	unsigned int esize, unsigned int n, unsigned int *available)
8299a2dd95SBruce Richardson {
8399a2dd95SBruce Richardson 	return __rte_ring_do_hts_dequeue_elem(r, obj_table, esize, n,
8499a2dd95SBruce Richardson 		RTE_RING_QUEUE_FIXED, available);
8599a2dd95SBruce Richardson }
8699a2dd95SBruce Richardson 
8799a2dd95SBruce Richardson /**
8899a2dd95SBruce Richardson  * Enqueue several objects on the HTS ring (multi-producers safe).
8999a2dd95SBruce Richardson  *
9099a2dd95SBruce Richardson  * @param r
9199a2dd95SBruce Richardson  *   A pointer to the ring structure.
9299a2dd95SBruce Richardson  * @param obj_table
9399a2dd95SBruce Richardson  *   A pointer to a table of objects.
9499a2dd95SBruce Richardson  * @param esize
9599a2dd95SBruce Richardson  *   The size of ring element, in bytes. It must be a multiple of 4.
9699a2dd95SBruce Richardson  *   This must be the same value used while creating the ring. Otherwise
9799a2dd95SBruce Richardson  *   the results are undefined.
9899a2dd95SBruce Richardson  * @param n
9999a2dd95SBruce Richardson  *   The number of objects to add in the ring from the obj_table.
10099a2dd95SBruce Richardson  * @param free_space
10199a2dd95SBruce Richardson  *   if non-NULL, returns the amount of space in the ring after the
10299a2dd95SBruce Richardson  *   enqueue operation has finished.
10399a2dd95SBruce Richardson  * @return
10499a2dd95SBruce Richardson  *   - n: Actual number of objects enqueued.
10599a2dd95SBruce Richardson  */
10699a2dd95SBruce Richardson static __rte_always_inline unsigned int
10799a2dd95SBruce Richardson rte_ring_mp_hts_enqueue_burst_elem(struct rte_ring *r, const void *obj_table,
10899a2dd95SBruce Richardson 	unsigned int esize, unsigned int n, unsigned int *free_space)
10999a2dd95SBruce Richardson {
11099a2dd95SBruce Richardson 	return __rte_ring_do_hts_enqueue_elem(r, obj_table, esize, n,
11199a2dd95SBruce Richardson 			RTE_RING_QUEUE_VARIABLE, free_space);
11299a2dd95SBruce Richardson }
11399a2dd95SBruce Richardson 
11499a2dd95SBruce Richardson /**
11599a2dd95SBruce Richardson  * Dequeue several objects from an HTS  ring (multi-consumers safe).
11699a2dd95SBruce Richardson  * When the requested objects are more than the available objects,
11799a2dd95SBruce Richardson  * only dequeue the actual number of objects.
11899a2dd95SBruce Richardson  *
11999a2dd95SBruce Richardson  * @param r
12099a2dd95SBruce Richardson  *   A pointer to the ring structure.
12199a2dd95SBruce Richardson  * @param obj_table
12299a2dd95SBruce Richardson  *   A pointer to a table of objects that will be filled.
12399a2dd95SBruce Richardson  * @param esize
12499a2dd95SBruce Richardson  *   The size of ring element, in bytes. It must be a multiple of 4.
12599a2dd95SBruce Richardson  *   This must be the same value used while creating the ring. Otherwise
12699a2dd95SBruce Richardson  *   the results are undefined.
12799a2dd95SBruce Richardson  * @param n
12899a2dd95SBruce Richardson  *   The number of objects to dequeue from the ring to the obj_table.
12999a2dd95SBruce Richardson  * @param available
13099a2dd95SBruce Richardson  *   If non-NULL, returns the number of remaining ring entries after the
13199a2dd95SBruce Richardson  *   dequeue has finished.
13299a2dd95SBruce Richardson  * @return
13399a2dd95SBruce Richardson  *   - n: Actual number of objects dequeued, 0 if ring is empty
13499a2dd95SBruce Richardson  */
13599a2dd95SBruce Richardson static __rte_always_inline unsigned int
13699a2dd95SBruce Richardson rte_ring_mc_hts_dequeue_burst_elem(struct rte_ring *r, void *obj_table,
13799a2dd95SBruce Richardson 	unsigned int esize, unsigned int n, unsigned int *available)
13899a2dd95SBruce Richardson {
13999a2dd95SBruce Richardson 	return __rte_ring_do_hts_dequeue_elem(r, obj_table, esize, n,
14099a2dd95SBruce Richardson 			RTE_RING_QUEUE_VARIABLE, available);
14199a2dd95SBruce Richardson }
14299a2dd95SBruce Richardson 
14399a2dd95SBruce Richardson /**
14499a2dd95SBruce Richardson  * Enqueue several objects on the HTS ring (multi-producers safe).
14599a2dd95SBruce Richardson  *
14699a2dd95SBruce Richardson  * @param r
14799a2dd95SBruce Richardson  *   A pointer to the ring structure.
14899a2dd95SBruce Richardson  * @param obj_table
14999a2dd95SBruce Richardson  *   A pointer to a table of void * pointers (objects).
15099a2dd95SBruce Richardson  * @param n
15199a2dd95SBruce Richardson  *   The number of objects to add in the ring from the obj_table.
15299a2dd95SBruce Richardson  * @param free_space
15399a2dd95SBruce Richardson  *   if non-NULL, returns the amount of space in the ring after the
15499a2dd95SBruce Richardson  *   enqueue operation has finished.
15599a2dd95SBruce Richardson  * @return
15699a2dd95SBruce Richardson  *   The number of objects enqueued, either 0 or n
15799a2dd95SBruce Richardson  */
15899a2dd95SBruce Richardson static __rte_always_inline unsigned int
15999a2dd95SBruce Richardson rte_ring_mp_hts_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
16099a2dd95SBruce Richardson 			 unsigned int n, unsigned int *free_space)
16199a2dd95SBruce Richardson {
16299a2dd95SBruce Richardson 	return rte_ring_mp_hts_enqueue_bulk_elem(r, obj_table,
16399a2dd95SBruce Richardson 			sizeof(uintptr_t), n, free_space);
16499a2dd95SBruce Richardson }
16599a2dd95SBruce Richardson 
16699a2dd95SBruce Richardson /**
16799a2dd95SBruce Richardson  * Dequeue several objects from an HTS ring (multi-consumers safe).
16899a2dd95SBruce Richardson  *
16999a2dd95SBruce Richardson  * @param r
17099a2dd95SBruce Richardson  *   A pointer to the ring structure.
17199a2dd95SBruce Richardson  * @param obj_table
17299a2dd95SBruce Richardson  *   A pointer to a table of void * pointers (objects) that will be filled.
17399a2dd95SBruce Richardson  * @param n
17499a2dd95SBruce Richardson  *   The number of objects to dequeue from the ring to the obj_table.
17599a2dd95SBruce Richardson  * @param available
17699a2dd95SBruce Richardson  *   If non-NULL, returns the number of remaining ring entries after the
17799a2dd95SBruce Richardson  *   dequeue has finished.
17899a2dd95SBruce Richardson  * @return
17999a2dd95SBruce Richardson  *   The number of objects dequeued, either 0 or n
18099a2dd95SBruce Richardson  */
18199a2dd95SBruce Richardson static __rte_always_inline unsigned int
18299a2dd95SBruce Richardson rte_ring_mc_hts_dequeue_bulk(struct rte_ring *r, void **obj_table,
18399a2dd95SBruce Richardson 		unsigned int n, unsigned int *available)
18499a2dd95SBruce Richardson {
18599a2dd95SBruce Richardson 	return rte_ring_mc_hts_dequeue_bulk_elem(r, obj_table,
18699a2dd95SBruce Richardson 			sizeof(uintptr_t), n, available);
18799a2dd95SBruce Richardson }
18899a2dd95SBruce Richardson 
18999a2dd95SBruce Richardson /**
19099a2dd95SBruce Richardson  * Enqueue several objects on the HTS ring (multi-producers safe).
19199a2dd95SBruce Richardson  *
19299a2dd95SBruce Richardson  * @param r
19399a2dd95SBruce Richardson  *   A pointer to the ring structure.
19499a2dd95SBruce Richardson  * @param obj_table
19599a2dd95SBruce Richardson  *   A pointer to a table of void * pointers (objects).
19699a2dd95SBruce Richardson  * @param n
19799a2dd95SBruce Richardson  *   The number of objects to add in the ring from the obj_table.
19899a2dd95SBruce Richardson  * @param free_space
19999a2dd95SBruce Richardson  *   if non-NULL, returns the amount of space in the ring after the
20099a2dd95SBruce Richardson  *   enqueue operation has finished.
20199a2dd95SBruce Richardson  * @return
20299a2dd95SBruce Richardson  *   - n: Actual number of objects enqueued.
20399a2dd95SBruce Richardson  */
20499a2dd95SBruce Richardson static __rte_always_inline unsigned int
20599a2dd95SBruce Richardson rte_ring_mp_hts_enqueue_burst(struct rte_ring *r, void * const *obj_table,
20699a2dd95SBruce Richardson 			 unsigned int n, unsigned int *free_space)
20799a2dd95SBruce Richardson {
20899a2dd95SBruce Richardson 	return rte_ring_mp_hts_enqueue_burst_elem(r, obj_table,
20999a2dd95SBruce Richardson 			sizeof(uintptr_t), n, free_space);
21099a2dd95SBruce Richardson }
21199a2dd95SBruce Richardson 
21299a2dd95SBruce Richardson /**
21399a2dd95SBruce Richardson  * Dequeue several objects from an HTS  ring (multi-consumers safe).
21499a2dd95SBruce Richardson  * When the requested objects are more than the available objects,
21599a2dd95SBruce Richardson  * only dequeue the actual number of objects.
21699a2dd95SBruce Richardson  *
21799a2dd95SBruce Richardson  * @param r
21899a2dd95SBruce Richardson  *   A pointer to the ring structure.
21999a2dd95SBruce Richardson  * @param obj_table
22099a2dd95SBruce Richardson  *   A pointer to a table of void * pointers (objects) that will be filled.
22199a2dd95SBruce Richardson  * @param n
22299a2dd95SBruce Richardson  *   The number of objects to dequeue from the ring to the obj_table.
22399a2dd95SBruce Richardson  * @param available
22499a2dd95SBruce Richardson  *   If non-NULL, returns the number of remaining ring entries after the
22599a2dd95SBruce Richardson  *   dequeue has finished.
22699a2dd95SBruce Richardson  * @return
22799a2dd95SBruce Richardson  *   - n: Actual number of objects dequeued, 0 if ring is empty
22899a2dd95SBruce Richardson  */
22999a2dd95SBruce Richardson static __rte_always_inline unsigned int
23099a2dd95SBruce Richardson rte_ring_mc_hts_dequeue_burst(struct rte_ring *r, void **obj_table,
23199a2dd95SBruce Richardson 		unsigned int n, unsigned int *available)
23299a2dd95SBruce Richardson {
23399a2dd95SBruce Richardson 	return rte_ring_mc_hts_dequeue_burst_elem(r, obj_table,
23499a2dd95SBruce Richardson 			sizeof(uintptr_t), n, available);
23599a2dd95SBruce Richardson }
23699a2dd95SBruce Richardson 
23799a2dd95SBruce Richardson #ifdef __cplusplus
23899a2dd95SBruce Richardson }
23999a2dd95SBruce Richardson #endif
24099a2dd95SBruce Richardson 
24199a2dd95SBruce Richardson #endif /* _RTE_RING_HTS_H_ */
242