1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019 Arm Limited 3 */ 4 5 #include <rte_malloc.h> 6 #include <rte_ring.h> 7 #include <rte_ring_elem.h> 8 9 /* API type to call 10 * rte_ring_<sp/mp or sc/mc>_enqueue_<bulk/burst> 11 * TEST_RING_THREAD_DEF - Uses configured SPSC/MPMC calls 12 * TEST_RING_THREAD_SPSC - Calls SP or SC API 13 * TEST_RING_THREAD_MPMC - Calls MP or MC API 14 */ 15 #define TEST_RING_THREAD_DEF 1 16 #define TEST_RING_THREAD_SPSC 2 17 #define TEST_RING_THREAD_MPMC 4 18 19 /* API type to call 20 * TEST_RING_ELEM_SINGLE - Calls single element APIs 21 * TEST_RING_ELEM_BULK - Calls bulk APIs 22 * TEST_RING_ELEM_BURST - Calls burst APIs 23 */ 24 #define TEST_RING_ELEM_SINGLE 8 25 #define TEST_RING_ELEM_BULK 16 26 #define TEST_RING_ELEM_BURST 32 27 28 #define TEST_RING_IGNORE_API_TYPE ~0U 29 30 /* This function is placed here as it is required for both 31 * performance and functional tests. 32 */ 33 static inline struct rte_ring* 34 test_ring_create(const char *name, int esize, unsigned int count, 35 int socket_id, unsigned int flags) 36 { 37 /* Legacy queue APIs? */ 38 if (esize == -1) 39 return rte_ring_create(name, count, socket_id, flags); 40 else 41 return rte_ring_create_elem(name, esize, count, 42 socket_id, flags); 43 } 44 45 static inline void* 46 test_ring_inc_ptr(void *obj, int esize, unsigned int n) 47 { 48 size_t sz; 49 50 sz = sizeof(void *); 51 /* Legacy queue APIs? */ 52 if (esize != -1) 53 sz = esize; 54 55 return (void *)((uint32_t *)obj + (n * sz / sizeof(uint32_t))); 56 } 57 58 static inline void 59 test_ring_mem_copy(void *dst, void * const *src, int esize, unsigned int num) 60 { 61 size_t sz; 62 63 sz = num * sizeof(void *); 64 if (esize != -1) 65 sz = esize * num; 66 67 memcpy(dst, src, sz); 68 } 69 70 /* Copy to the ring memory */ 71 static inline void 72 test_ring_copy_to(struct rte_ring_zc_data *zcd, void * const *src, int esize, 73 unsigned int num) 74 { 75 test_ring_mem_copy(zcd->ptr1, src, esize, zcd->n1); 76 if (zcd->n1 != num) { 77 if (esize == -1) 78 src = src + zcd->n1; 79 else 80 src = (void * const *)((const uint32_t *)src + 81 (zcd->n1 * esize / sizeof(uint32_t))); 82 test_ring_mem_copy(zcd->ptr2, src, 83 esize, num - zcd->n1); 84 } 85 } 86 87 /* Copy from the ring memory */ 88 static inline void 89 test_ring_copy_from(struct rte_ring_zc_data *zcd, void *dst, int esize, 90 unsigned int num) 91 { 92 test_ring_mem_copy(dst, zcd->ptr1, esize, zcd->n1); 93 94 if (zcd->n1 != num) { 95 dst = test_ring_inc_ptr(dst, esize, zcd->n1); 96 test_ring_mem_copy(dst, zcd->ptr2, esize, num - zcd->n1); 97 } 98 } 99 100 static __rte_always_inline unsigned int 101 test_ring_enqueue(struct rte_ring *r, void **obj, int esize, unsigned int n, 102 unsigned int api_type) 103 { 104 /* Legacy queue APIs? */ 105 if (esize == -1) 106 switch (api_type) { 107 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE): 108 return rte_ring_enqueue(r, *obj); 109 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE): 110 return rte_ring_sp_enqueue(r, *obj); 111 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE): 112 return rte_ring_mp_enqueue(r, *obj); 113 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK): 114 return rte_ring_enqueue_bulk(r, obj, n, NULL); 115 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK): 116 return rte_ring_sp_enqueue_bulk(r, obj, n, NULL); 117 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK): 118 return rte_ring_mp_enqueue_bulk(r, obj, n, NULL); 119 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST): 120 return rte_ring_enqueue_burst(r, obj, n, NULL); 121 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST): 122 return rte_ring_sp_enqueue_burst(r, obj, n, NULL); 123 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST): 124 return rte_ring_mp_enqueue_burst(r, obj, n, NULL); 125 default: 126 printf("Invalid API type\n"); 127 return 0; 128 } 129 else 130 switch (api_type) { 131 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE): 132 return rte_ring_enqueue_elem(r, obj, esize); 133 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE): 134 return rte_ring_sp_enqueue_elem(r, obj, esize); 135 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE): 136 return rte_ring_mp_enqueue_elem(r, obj, esize); 137 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK): 138 return rte_ring_enqueue_bulk_elem(r, obj, esize, n, 139 NULL); 140 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK): 141 return rte_ring_sp_enqueue_bulk_elem(r, obj, esize, n, 142 NULL); 143 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK): 144 return rte_ring_mp_enqueue_bulk_elem(r, obj, esize, n, 145 NULL); 146 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST): 147 return rte_ring_enqueue_burst_elem(r, obj, esize, n, 148 NULL); 149 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST): 150 return rte_ring_sp_enqueue_burst_elem(r, obj, esize, n, 151 NULL); 152 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST): 153 return rte_ring_mp_enqueue_burst_elem(r, obj, esize, n, 154 NULL); 155 default: 156 printf("Invalid API type\n"); 157 return 0; 158 } 159 } 160 161 static __rte_always_inline unsigned int 162 test_ring_dequeue(struct rte_ring *r, void **obj, int esize, unsigned int n, 163 unsigned int api_type) 164 { 165 /* Legacy queue APIs? */ 166 if (esize == -1) 167 switch (api_type) { 168 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE): 169 return rte_ring_dequeue(r, obj); 170 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE): 171 return rte_ring_sc_dequeue(r, obj); 172 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE): 173 return rte_ring_mc_dequeue(r, obj); 174 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK): 175 return rte_ring_dequeue_bulk(r, obj, n, NULL); 176 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK): 177 return rte_ring_sc_dequeue_bulk(r, obj, n, NULL); 178 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK): 179 return rte_ring_mc_dequeue_bulk(r, obj, n, NULL); 180 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST): 181 return rte_ring_dequeue_burst(r, obj, n, NULL); 182 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST): 183 return rte_ring_sc_dequeue_burst(r, obj, n, NULL); 184 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST): 185 return rte_ring_mc_dequeue_burst(r, obj, n, NULL); 186 default: 187 printf("Invalid API type\n"); 188 return 0; 189 } 190 else 191 switch (api_type) { 192 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE): 193 return rte_ring_dequeue_elem(r, obj, esize); 194 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE): 195 return rte_ring_sc_dequeue_elem(r, obj, esize); 196 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE): 197 return rte_ring_mc_dequeue_elem(r, obj, esize); 198 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK): 199 return rte_ring_dequeue_bulk_elem(r, obj, esize, 200 n, NULL); 201 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK): 202 return rte_ring_sc_dequeue_bulk_elem(r, obj, esize, 203 n, NULL); 204 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK): 205 return rte_ring_mc_dequeue_bulk_elem(r, obj, esize, 206 n, NULL); 207 case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST): 208 return rte_ring_dequeue_burst_elem(r, obj, esize, 209 n, NULL); 210 case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST): 211 return rte_ring_sc_dequeue_burst_elem(r, obj, esize, 212 n, NULL); 213 case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST): 214 return rte_ring_mc_dequeue_burst_elem(r, obj, esize, 215 n, NULL); 216 default: 217 printf("Invalid API type\n"); 218 return 0; 219 } 220 } 221 222 /* This function is placed here as it is required for both 223 * performance and functional tests. 224 */ 225 static __rte_always_inline void * 226 test_ring_calloc(unsigned int rsize, int esize) 227 { 228 unsigned int sz; 229 void *p; 230 231 /* Legacy queue APIs? */ 232 if (esize == -1) 233 sz = sizeof(void *); 234 else 235 sz = esize; 236 237 p = rte_zmalloc(NULL, rsize * sz, RTE_CACHE_LINE_SIZE); 238 if (p == NULL) 239 printf("Failed to allocate memory\n"); 240 241 return p; 242 } 243