1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Arm Limited 3 */ 4 5 #ifndef _RTE_BITOPS_H_ 6 #define _RTE_BITOPS_H_ 7 8 /** 9 * @file 10 * Bit Operations 11 * 12 * This file defines a family of APIs for bit operations 13 * without enforcing memory ordering. 14 */ 15 16 #include <stdint.h> 17 #include <rte_debug.h> 18 #include <rte_compat.h> 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /** 25 * Get the uint64_t value for a specified bit set. 26 * 27 * @param nr 28 * The bit number in range of 0 to 63. 29 */ 30 #define RTE_BIT64(nr) (UINT64_C(1) << (nr)) 31 32 /** 33 * Get the uint32_t value for a specified bit set. 34 * 35 * @param nr 36 * The bit number in range of 0 to 31. 37 */ 38 #define RTE_BIT32(nr) (UINT32_C(1) << (nr)) 39 40 /*------------------------ 32-bit relaxed operations ------------------------*/ 41 42 /** 43 * @warning 44 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 45 * 46 * Get the target bit from a 32-bit value without memory ordering. 47 * 48 * @param nr 49 * The target bit to get. 50 * @param addr 51 * The address holding the bit. 52 * @return 53 * The target bit. 54 */ 55 __rte_experimental 56 static inline uint32_t 57 rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr) 58 { 59 RTE_ASSERT(nr < 32); 60 61 uint32_t mask = UINT32_C(1) << nr; 62 return (*addr) & mask; 63 } 64 65 /** 66 * @warning 67 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 68 * 69 * Set the target bit in a 32-bit value to 1 without memory ordering. 70 * 71 * @param nr 72 * The target bit to set. 73 * @param addr 74 * The address holding the bit. 75 */ 76 __rte_experimental 77 static inline void 78 rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr) 79 { 80 RTE_ASSERT(nr < 32); 81 82 uint32_t mask = RTE_BIT32(nr); 83 *addr = (*addr) | mask; 84 } 85 86 /** 87 * @warning 88 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 89 * 90 * Clear the target bit in a 32-bit value to 0 without memory ordering. 91 * 92 * @param nr 93 * The target bit to clear. 94 * @param addr 95 * The address holding the bit. 96 */ 97 __rte_experimental 98 static inline void 99 rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr) 100 { 101 RTE_ASSERT(nr < 32); 102 103 uint32_t mask = RTE_BIT32(nr); 104 *addr = (*addr) & (~mask); 105 } 106 107 /** 108 * @warning 109 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 110 * 111 * Return the original bit from a 32-bit value, then set it to 1 without 112 * memory ordering. 113 * 114 * @param nr 115 * The target bit to get and set. 116 * @param addr 117 * The address holding the bit. 118 * @return 119 * The original bit. 120 */ 121 __rte_experimental 122 static inline uint32_t 123 rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr) 124 { 125 RTE_ASSERT(nr < 32); 126 127 uint32_t mask = RTE_BIT32(nr); 128 uint32_t val = *addr; 129 *addr = val | mask; 130 return val & mask; 131 } 132 133 /** 134 * @warning 135 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 136 * 137 * Return the original bit from a 32-bit value, then clear it to 0 without 138 * memory ordering. 139 * 140 * @param nr 141 * The target bit to get and clear. 142 * @param addr 143 * The address holding the bit. 144 * @return 145 * The original bit. 146 */ 147 __rte_experimental 148 static inline uint32_t 149 rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr) 150 { 151 RTE_ASSERT(nr < 32); 152 153 uint32_t mask = RTE_BIT32(nr); 154 uint32_t val = *addr; 155 *addr = val & (~mask); 156 return val & mask; 157 } 158 159 /*------------------------ 64-bit relaxed operations ------------------------*/ 160 161 /** 162 * @warning 163 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 164 * 165 * Get the target bit from a 64-bit value without memory ordering. 166 * 167 * @param nr 168 * The target bit to get. 169 * @param addr 170 * The address holding the bit. 171 * @return 172 * The target bit. 173 */ 174 __rte_experimental 175 static inline uint64_t 176 rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr) 177 { 178 RTE_ASSERT(nr < 64); 179 180 uint64_t mask = RTE_BIT64(nr); 181 return (*addr) & mask; 182 } 183 184 /** 185 * @warning 186 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 187 * 188 * Set the target bit in a 64-bit value to 1 without memory ordering. 189 * 190 * @param nr 191 * The target bit to set. 192 * @param addr 193 * The address holding the bit. 194 */ 195 __rte_experimental 196 static inline void 197 rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr) 198 { 199 RTE_ASSERT(nr < 64); 200 201 uint64_t mask = RTE_BIT64(nr); 202 (*addr) = (*addr) | mask; 203 } 204 205 /** 206 * @warning 207 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 208 * 209 * Clear the target bit in a 64-bit value to 0 without memory ordering. 210 * 211 * @param nr 212 * The target bit to clear. 213 * @param addr 214 * The address holding the bit. 215 */ 216 __rte_experimental 217 static inline void 218 rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr) 219 { 220 RTE_ASSERT(nr < 64); 221 222 uint64_t mask = RTE_BIT64(nr); 223 *addr = (*addr) & (~mask); 224 } 225 226 /** 227 * @warning 228 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 229 * 230 * Return the original bit from a 64-bit value, then set it to 1 without 231 * memory ordering. 232 * 233 * @param nr 234 * The target bit to get and set. 235 * @param addr 236 * The address holding the bit. 237 * @return 238 * The original bit. 239 */ 240 __rte_experimental 241 static inline uint64_t 242 rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr) 243 { 244 RTE_ASSERT(nr < 64); 245 246 uint64_t mask = RTE_BIT64(nr); 247 uint64_t val = *addr; 248 *addr = val | mask; 249 return val; 250 } 251 252 /** 253 * @warning 254 * @b EXPERIMENTAL: this API may change, or be removed, without prior notice 255 * 256 * Return the original bit from a 64-bit value, then clear it to 0 without 257 * memory ordering. 258 * 259 * @param nr 260 * The target bit to get and clear. 261 * @param addr 262 * The address holding the bit. 263 * @return 264 * The original bit. 265 */ 266 __rte_experimental 267 static inline uint64_t 268 rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr) 269 { 270 RTE_ASSERT(nr < 64); 271 272 uint64_t mask = RTE_BIT64(nr); 273 uint64_t val = *addr; 274 *addr = val & (~mask); 275 return val & mask; 276 } 277 278 #ifdef __cplusplus 279 } 280 #endif 281 282 #endif /* _RTE_BITOPS_H_ */ 283