1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright (c) 2010-2020 Intel Corporation 4 * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org 5 * All rights reserved. 6 * Derived from FreeBSD's bufring.h 7 * Used as BSD-3 Licensed with permission from Kip Macy. 8 */ 9 10 #ifndef _RTE_RING_HTS_H_ 11 #define _RTE_RING_HTS_H_ 12 13 /** 14 * @file rte_ring_hts.h 15 * It is not recommended to include this file directly. 16 * Please include <rte_ring.h> instead. 17 * 18 * Contains functions for serialized, aka Head-Tail Sync (HTS) ring mode. 19 * In that mode enqueue/dequeue operation is fully serialized: 20 * at any given moment only one enqueue/dequeue operation can proceed. 21 * This is achieved by allowing a thread to proceed with changing head.value 22 * only when head.value == tail.value. 23 * Both head and tail values are updated atomically (as one 64-bit value). 24 * To achieve that 64-bit CAS is used by head update routine. 25 */ 26 27 #include <rte_ring_hts_elem_pvt.h> 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 /** 34 * Enqueue several objects on the HTS ring (multi-producers safe). 35 * 36 * @param r 37 * A pointer to the ring structure. 38 * @param obj_table 39 * A pointer to a table of objects. 40 * @param esize 41 * The size of ring element, in bytes. It must be a multiple of 4. 42 * This must be the same value used while creating the ring. Otherwise 43 * the results are undefined. 44 * @param n 45 * The number of objects to add in the ring from the obj_table. 46 * @param free_space 47 * if non-NULL, returns the amount of space in the ring after the 48 * enqueue operation has finished. 49 * @return 50 * The number of objects enqueued, either 0 or n 51 */ 52 static __rte_always_inline unsigned int 53 rte_ring_mp_hts_enqueue_bulk_elem(struct rte_ring *r, const void *obj_table, 54 unsigned int esize, unsigned int n, unsigned int *free_space) 55 { 56 return __rte_ring_do_hts_enqueue_elem(r, obj_table, esize, n, 57 RTE_RING_QUEUE_FIXED, free_space); 58 } 59 60 /** 61 * Dequeue several objects from an HTS ring (multi-consumers safe). 62 * 63 * @param r 64 * A pointer to the ring structure. 65 * @param obj_table 66 * A pointer to a table of objects that will be filled. 67 * @param esize 68 * The size of ring element, in bytes. It must be a multiple of 4. 69 * This must be the same value used while creating the ring. Otherwise 70 * the results are undefined. 71 * @param n 72 * The number of objects to dequeue from the ring to the obj_table. 73 * @param available 74 * If non-NULL, returns the number of remaining ring entries after the 75 * dequeue has finished. 76 * @return 77 * The number of objects dequeued, either 0 or n 78 */ 79 static __rte_always_inline unsigned int 80 rte_ring_mc_hts_dequeue_bulk_elem(struct rte_ring *r, void *obj_table, 81 unsigned int esize, unsigned int n, unsigned int *available) 82 { 83 return __rte_ring_do_hts_dequeue_elem(r, obj_table, esize, n, 84 RTE_RING_QUEUE_FIXED, available); 85 } 86 87 /** 88 * Enqueue several objects on the HTS ring (multi-producers safe). 89 * 90 * @param r 91 * A pointer to the ring structure. 92 * @param obj_table 93 * A pointer to a table of objects. 94 * @param esize 95 * The size of ring element, in bytes. It must be a multiple of 4. 96 * This must be the same value used while creating the ring. Otherwise 97 * the results are undefined. 98 * @param n 99 * The number of objects to add in the ring from the obj_table. 100 * @param free_space 101 * if non-NULL, returns the amount of space in the ring after the 102 * enqueue operation has finished. 103 * @return 104 * - n: Actual number of objects enqueued. 105 */ 106 static __rte_always_inline unsigned int 107 rte_ring_mp_hts_enqueue_burst_elem(struct rte_ring *r, const void *obj_table, 108 unsigned int esize, unsigned int n, unsigned int *free_space) 109 { 110 return __rte_ring_do_hts_enqueue_elem(r, obj_table, esize, n, 111 RTE_RING_QUEUE_VARIABLE, free_space); 112 } 113 114 /** 115 * Dequeue several objects from an HTS ring (multi-consumers safe). 116 * When the requested objects are more than the available objects, 117 * only dequeue the actual number of objects. 118 * 119 * @param r 120 * A pointer to the ring structure. 121 * @param obj_table 122 * A pointer to a table of objects that will be filled. 123 * @param esize 124 * The size of ring element, in bytes. It must be a multiple of 4. 125 * This must be the same value used while creating the ring. Otherwise 126 * the results are undefined. 127 * @param n 128 * The number of objects to dequeue from the ring to the obj_table. 129 * @param available 130 * If non-NULL, returns the number of remaining ring entries after the 131 * dequeue has finished. 132 * @return 133 * - n: Actual number of objects dequeued, 0 if ring is empty 134 */ 135 static __rte_always_inline unsigned int 136 rte_ring_mc_hts_dequeue_burst_elem(struct rte_ring *r, void *obj_table, 137 unsigned int esize, unsigned int n, unsigned int *available) 138 { 139 return __rte_ring_do_hts_dequeue_elem(r, obj_table, esize, n, 140 RTE_RING_QUEUE_VARIABLE, available); 141 } 142 143 /** 144 * Enqueue several objects on the HTS ring (multi-producers safe). 145 * 146 * @param r 147 * A pointer to the ring structure. 148 * @param obj_table 149 * A pointer to a table of void * pointers (objects). 150 * @param n 151 * The number of objects to add in the ring from the obj_table. 152 * @param free_space 153 * if non-NULL, returns the amount of space in the ring after the 154 * enqueue operation has finished. 155 * @return 156 * The number of objects enqueued, either 0 or n 157 */ 158 static __rte_always_inline unsigned int 159 rte_ring_mp_hts_enqueue_bulk(struct rte_ring *r, void * const *obj_table, 160 unsigned int n, unsigned int *free_space) 161 { 162 return rte_ring_mp_hts_enqueue_bulk_elem(r, obj_table, 163 sizeof(uintptr_t), n, free_space); 164 } 165 166 /** 167 * Dequeue several objects from an HTS ring (multi-consumers safe). 168 * 169 * @param r 170 * A pointer to the ring structure. 171 * @param obj_table 172 * A pointer to a table of void * pointers (objects) that will be filled. 173 * @param n 174 * The number of objects to dequeue from the ring to the obj_table. 175 * @param available 176 * If non-NULL, returns the number of remaining ring entries after the 177 * dequeue has finished. 178 * @return 179 * The number of objects dequeued, either 0 or n 180 */ 181 static __rte_always_inline unsigned int 182 rte_ring_mc_hts_dequeue_bulk(struct rte_ring *r, void **obj_table, 183 unsigned int n, unsigned int *available) 184 { 185 return rte_ring_mc_hts_dequeue_bulk_elem(r, obj_table, 186 sizeof(uintptr_t), n, available); 187 } 188 189 /** 190 * Enqueue several objects on the HTS ring (multi-producers safe). 191 * 192 * @param r 193 * A pointer to the ring structure. 194 * @param obj_table 195 * A pointer to a table of void * pointers (objects). 196 * @param n 197 * The number of objects to add in the ring from the obj_table. 198 * @param free_space 199 * if non-NULL, returns the amount of space in the ring after the 200 * enqueue operation has finished. 201 * @return 202 * - n: Actual number of objects enqueued. 203 */ 204 static __rte_always_inline unsigned int 205 rte_ring_mp_hts_enqueue_burst(struct rte_ring *r, void * const *obj_table, 206 unsigned int n, unsigned int *free_space) 207 { 208 return rte_ring_mp_hts_enqueue_burst_elem(r, obj_table, 209 sizeof(uintptr_t), n, free_space); 210 } 211 212 /** 213 * Dequeue several objects from an HTS ring (multi-consumers safe). 214 * When the requested objects are more than the available objects, 215 * only dequeue the actual number of objects. 216 * 217 * @param r 218 * A pointer to the ring structure. 219 * @param obj_table 220 * A pointer to a table of void * pointers (objects) that will be filled. 221 * @param n 222 * The number of objects to dequeue from the ring to the obj_table. 223 * @param available 224 * If non-NULL, returns the number of remaining ring entries after the 225 * dequeue has finished. 226 * @return 227 * - n: Actual number of objects dequeued, 0 if ring is empty 228 */ 229 static __rte_always_inline unsigned int 230 rte_ring_mc_hts_dequeue_burst(struct rte_ring *r, void **obj_table, 231 unsigned int n, unsigned int *available) 232 { 233 return rte_ring_mc_hts_dequeue_burst_elem(r, obj_table, 234 sizeof(uintptr_t), n, available); 235 } 236 237 #ifdef __cplusplus 238 } 239 #endif 240 241 #endif /* _RTE_RING_HTS_H_ */ 242