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