199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2020 Arm Limited 3916c50ddSTyler Retzlaff * Copyright(c) 2010-2019 Intel Corporation 4916c50ddSTyler Retzlaff * Copyright(c) 2023 Microsoft Corporation 5471de107SMattias Rönnblom * Copyright(c) 2024 Ericsson AB 699a2dd95SBruce Richardson */ 799a2dd95SBruce Richardson 899a2dd95SBruce Richardson #ifndef _RTE_BITOPS_H_ 999a2dd95SBruce Richardson #define _RTE_BITOPS_H_ 1099a2dd95SBruce Richardson 1199a2dd95SBruce Richardson /** 1299a2dd95SBruce Richardson * @file 1399a2dd95SBruce Richardson * Bit Operations 1499a2dd95SBruce Richardson * 15471de107SMattias Rönnblom * This file provides functionality for low-level, single-word 16471de107SMattias Rönnblom * arithmetic and bit-level operations, such as counting or 17471de107SMattias Rönnblom * setting individual bits. 1899a2dd95SBruce Richardson */ 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson #include <stdint.h> 2130764c0fSStephen Hemminger 22471de107SMattias Rönnblom #include <rte_compat.h> 2399a2dd95SBruce Richardson #include <rte_debug.h> 2435326b61SMattias Rönnblom #include <rte_stdatomic.h> 2599a2dd95SBruce Richardson 26d7e9c02cSBrian Dooley #ifdef __cplusplus 27d7e9c02cSBrian Dooley extern "C" { 28d7e9c02cSBrian Dooley #endif 29d7e9c02cSBrian Dooley 3099a2dd95SBruce Richardson /** 3199a2dd95SBruce Richardson * Get the uint64_t value for a specified bit set. 3299a2dd95SBruce Richardson * 3399a2dd95SBruce Richardson * @param nr 3499a2dd95SBruce Richardson * The bit number in range of 0 to 63. 3599a2dd95SBruce Richardson */ 3699a2dd95SBruce Richardson #define RTE_BIT64(nr) (UINT64_C(1) << (nr)) 3799a2dd95SBruce Richardson 3899a2dd95SBruce Richardson /** 3999a2dd95SBruce Richardson * Get the uint32_t value for a specified bit set. 4099a2dd95SBruce Richardson * 4199a2dd95SBruce Richardson * @param nr 4299a2dd95SBruce Richardson * The bit number in range of 0 to 31. 4399a2dd95SBruce Richardson */ 4499a2dd95SBruce Richardson #define RTE_BIT32(nr) (UINT32_C(1) << (nr)) 4599a2dd95SBruce Richardson 461d8f2285SChengwen Feng /** 471d8f2285SChengwen Feng * Get the uint32_t shifted value. 481d8f2285SChengwen Feng * 491d8f2285SChengwen Feng * @param val 501d8f2285SChengwen Feng * The value to be shifted. 511d8f2285SChengwen Feng * @param nr 521d8f2285SChengwen Feng * The shift number in range of 0 to (32 - width of val). 531d8f2285SChengwen Feng */ 541d8f2285SChengwen Feng #define RTE_SHIFT_VAL32(val, nr) (UINT32_C(val) << (nr)) 551d8f2285SChengwen Feng 561d8f2285SChengwen Feng /** 571d8f2285SChengwen Feng * Get the uint64_t shifted value. 581d8f2285SChengwen Feng * 591d8f2285SChengwen Feng * @param val 601d8f2285SChengwen Feng * The value to be shifted. 611d8f2285SChengwen Feng * @param nr 621d8f2285SChengwen Feng * The shift number in range of 0 to (64 - width of val). 631d8f2285SChengwen Feng */ 641d8f2285SChengwen Feng #define RTE_SHIFT_VAL64(val, nr) (UINT64_C(val) << (nr)) 651d8f2285SChengwen Feng 661d8f2285SChengwen Feng /** 671d8f2285SChengwen Feng * Generate a contiguous 32-bit mask 681d8f2285SChengwen Feng * starting at bit position low and ending at position high. 691d8f2285SChengwen Feng * 701d8f2285SChengwen Feng * @param high 711d8f2285SChengwen Feng * High bit position. 721d8f2285SChengwen Feng * @param low 731d8f2285SChengwen Feng * Low bit position. 741d8f2285SChengwen Feng */ 751d8f2285SChengwen Feng #define RTE_GENMASK32(high, low) \ 761d8f2285SChengwen Feng (((~UINT32_C(0)) << (low)) & (~UINT32_C(0) >> (31u - (high)))) 771d8f2285SChengwen Feng 781d8f2285SChengwen Feng /** 791d8f2285SChengwen Feng * Generate a contiguous 64-bit mask 801d8f2285SChengwen Feng * starting at bit position low and ending at position high. 811d8f2285SChengwen Feng * 821d8f2285SChengwen Feng * @param high 831d8f2285SChengwen Feng * High bit position. 841d8f2285SChengwen Feng * @param low 851d8f2285SChengwen Feng * Low bit position. 861d8f2285SChengwen Feng */ 871d8f2285SChengwen Feng #define RTE_GENMASK64(high, low) \ 881d8f2285SChengwen Feng (((~UINT64_C(0)) << (low)) & (~UINT64_C(0) >> (63u - (high)))) 891d8f2285SChengwen Feng 901d8f2285SChengwen Feng /** 911d8f2285SChengwen Feng * Extract a 32-bit field element. 921d8f2285SChengwen Feng * 931d8f2285SChengwen Feng * @param mask 941d8f2285SChengwen Feng * Shifted mask. 951d8f2285SChengwen Feng * @param reg 961d8f2285SChengwen Feng * Value of entire bitfield. 971d8f2285SChengwen Feng */ 981d8f2285SChengwen Feng #define RTE_FIELD_GET32(mask, reg) \ 991d8f2285SChengwen Feng ((typeof(mask))(((reg) & (mask)) >> rte_ctz32(mask))) 1001d8f2285SChengwen Feng 1011d8f2285SChengwen Feng /** 1021d8f2285SChengwen Feng * Extract a 64-bit field element. 1031d8f2285SChengwen Feng * 1041d8f2285SChengwen Feng * @param mask 1051d8f2285SChengwen Feng * Shifted mask. 1061d8f2285SChengwen Feng * @param reg 1071d8f2285SChengwen Feng * Value of entire bitfield. 1081d8f2285SChengwen Feng */ 1091d8f2285SChengwen Feng #define RTE_FIELD_GET64(mask, reg) \ 1101d8f2285SChengwen Feng ((typeof(mask))(((reg) & (mask)) >> rte_ctz64(mask))) 1111d8f2285SChengwen Feng 112471de107SMattias Rönnblom /** 113471de107SMattias Rönnblom * @warning 114471de107SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 115471de107SMattias Rönnblom * 116471de107SMattias Rönnblom * Test bit in word. 117471de107SMattias Rönnblom * 118471de107SMattias Rönnblom * Generic selection macro to test the value of a bit in a 32-bit or 119471de107SMattias Rönnblom * 64-bit word. The type of operation depends on the type of the @c 120471de107SMattias Rönnblom * addr parameter. 121471de107SMattias Rönnblom * 122471de107SMattias Rönnblom * This macro does not give any guarantees in regards to memory 123471de107SMattias Rönnblom * ordering or atomicity. 124471de107SMattias Rönnblom * 125471de107SMattias Rönnblom * @param addr 126471de107SMattias Rönnblom * A pointer to the word to modify. 127471de107SMattias Rönnblom * @param nr 128471de107SMattias Rönnblom * The index of the bit. 129471de107SMattias Rönnblom */ 130471de107SMattias Rönnblom #define rte_bit_test(addr, nr) \ 131471de107SMattias Rönnblom _Generic((addr), \ 132471de107SMattias Rönnblom uint32_t *: __rte_bit_test32, \ 133471de107SMattias Rönnblom const uint32_t *: __rte_bit_test32, \ 1340883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_v_test32, \ 1350883d736SMattias Rönnblom const volatile uint32_t *: __rte_bit_v_test32, \ 136471de107SMattias Rönnblom uint64_t *: __rte_bit_test64, \ 1370883d736SMattias Rönnblom const uint64_t *: __rte_bit_test64, \ 1380883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_v_test64, \ 1390883d736SMattias Rönnblom const volatile uint64_t *: __rte_bit_v_test64) \ 140471de107SMattias Rönnblom (addr, nr) 141471de107SMattias Rönnblom 142471de107SMattias Rönnblom /** 143471de107SMattias Rönnblom * @warning 144471de107SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 145471de107SMattias Rönnblom * 146471de107SMattias Rönnblom * Set bit in word. 147471de107SMattias Rönnblom * 148471de107SMattias Rönnblom * Generic selection macro to set a bit in a 32-bit or 64-bit 149471de107SMattias Rönnblom * word. The type of operation depends on the type of the @c addr 150471de107SMattias Rönnblom * parameter. 151471de107SMattias Rönnblom * 152471de107SMattias Rönnblom * This macro does not give any guarantees in regards to memory 153471de107SMattias Rönnblom * ordering or atomicity. 154471de107SMattias Rönnblom * 155471de107SMattias Rönnblom * @param addr 156471de107SMattias Rönnblom * A pointer to the word to modify. 157471de107SMattias Rönnblom * @param nr 158471de107SMattias Rönnblom * The index of the bit. 159471de107SMattias Rönnblom */ 160471de107SMattias Rönnblom #define rte_bit_set(addr, nr) \ 161471de107SMattias Rönnblom _Generic((addr), \ 162471de107SMattias Rönnblom uint32_t *: __rte_bit_set32, \ 1630883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_v_set32, \ 1640883d736SMattias Rönnblom uint64_t *: __rte_bit_set64, \ 1650883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_v_set64) \ 166471de107SMattias Rönnblom (addr, nr) 167471de107SMattias Rönnblom 168471de107SMattias Rönnblom /** 169471de107SMattias Rönnblom * @warning 170471de107SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 171471de107SMattias Rönnblom * 172471de107SMattias Rönnblom * Clear bit in word. 173471de107SMattias Rönnblom * 174471de107SMattias Rönnblom * Generic selection macro to clear a bit in a 32-bit or 64-bit 175471de107SMattias Rönnblom * word. The type of operation depends on the type of the @c addr 176471de107SMattias Rönnblom * parameter. 177471de107SMattias Rönnblom * 178471de107SMattias Rönnblom * This macro does not give any guarantees in regards to memory 179471de107SMattias Rönnblom * ordering or atomicity. 180471de107SMattias Rönnblom * 181471de107SMattias Rönnblom * @param addr 182471de107SMattias Rönnblom * A pointer to the word to modify. 183471de107SMattias Rönnblom * @param nr 184471de107SMattias Rönnblom * The index of the bit. 185471de107SMattias Rönnblom */ 186471de107SMattias Rönnblom #define rte_bit_clear(addr, nr) \ 187471de107SMattias Rönnblom _Generic((addr), \ 188471de107SMattias Rönnblom uint32_t *: __rte_bit_clear32, \ 1890883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_v_clear32, \ 1900883d736SMattias Rönnblom uint64_t *: __rte_bit_clear64, \ 1910883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_v_clear64) \ 192471de107SMattias Rönnblom (addr, nr) 193471de107SMattias Rönnblom 194471de107SMattias Rönnblom /** 195471de107SMattias Rönnblom * @warning 196471de107SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 197471de107SMattias Rönnblom * 198471de107SMattias Rönnblom * Assign a value to a bit in word. 199471de107SMattias Rönnblom * 200471de107SMattias Rönnblom * Generic selection macro to assign a value to a bit in a 32-bit or 64-bit 201471de107SMattias Rönnblom * word. The type of operation depends on the type of the @c addr parameter. 202471de107SMattias Rönnblom * 203471de107SMattias Rönnblom * This macro does not give any guarantees in regards to memory 204471de107SMattias Rönnblom * ordering or atomicity. 205471de107SMattias Rönnblom * 206471de107SMattias Rönnblom * @param addr 207471de107SMattias Rönnblom * A pointer to the word to modify. 208471de107SMattias Rönnblom * @param nr 209471de107SMattias Rönnblom * The index of the bit. 210471de107SMattias Rönnblom * @param value 211471de107SMattias Rönnblom * The new value of the bit - true for '1', or false for '0'. 212471de107SMattias Rönnblom */ 213471de107SMattias Rönnblom #define rte_bit_assign(addr, nr, value) \ 214471de107SMattias Rönnblom _Generic((addr), \ 215471de107SMattias Rönnblom uint32_t *: __rte_bit_assign32, \ 2160883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_v_assign32, \ 2170883d736SMattias Rönnblom uint64_t *: __rte_bit_assign64, \ 2180883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_v_assign64) \ 219471de107SMattias Rönnblom (addr, nr, value) 220471de107SMattias Rönnblom 221471de107SMattias Rönnblom /** 222471de107SMattias Rönnblom * @warning 223471de107SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 224471de107SMattias Rönnblom * 225471de107SMattias Rönnblom * Flip a bit in word. 226471de107SMattias Rönnblom * 227471de107SMattias Rönnblom * Generic selection macro to change the value of a bit to '0' if '1' 228471de107SMattias Rönnblom * or '1' if '0' in a 32-bit or 64-bit word. The type of operation 229471de107SMattias Rönnblom * depends on the type of the @c addr parameter. 230471de107SMattias Rönnblom * 231471de107SMattias Rönnblom * This macro does not give any guarantees in regards to memory 232471de107SMattias Rönnblom * ordering or atomicity. 233471de107SMattias Rönnblom * 234471de107SMattias Rönnblom * @param addr 235471de107SMattias Rönnblom * A pointer to the word to modify. 236471de107SMattias Rönnblom * @param nr 237471de107SMattias Rönnblom * The index of the bit. 238471de107SMattias Rönnblom */ 239471de107SMattias Rönnblom #define rte_bit_flip(addr, nr) \ 240471de107SMattias Rönnblom _Generic((addr), \ 241471de107SMattias Rönnblom uint32_t *: __rte_bit_flip32, \ 2420883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_v_flip32, \ 2430883d736SMattias Rönnblom uint64_t *: __rte_bit_flip64, \ 2440883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_v_flip64) \ 245471de107SMattias Rönnblom (addr, nr) 246471de107SMattias Rönnblom 24735326b61SMattias Rönnblom /** 24835326b61SMattias Rönnblom * @warning 24935326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 25035326b61SMattias Rönnblom * 25135326b61SMattias Rönnblom * Test if a particular bit in a word is set with a particular memory 25235326b61SMattias Rönnblom * order. 25335326b61SMattias Rönnblom * 25435326b61SMattias Rönnblom * Test a bit with the resulting memory load ordered as per the 25535326b61SMattias Rönnblom * specified memory order. 25635326b61SMattias Rönnblom * 25735326b61SMattias Rönnblom * @param addr 25835326b61SMattias Rönnblom * A pointer to the word to query. 25935326b61SMattias Rönnblom * @param nr 26035326b61SMattias Rönnblom * The index of the bit. 26135326b61SMattias Rönnblom * @param memory_order 26235326b61SMattias Rönnblom * The memory order to use. 26335326b61SMattias Rönnblom * @return 26435326b61SMattias Rönnblom * Returns true if the bit is set, and false otherwise. 26535326b61SMattias Rönnblom */ 26635326b61SMattias Rönnblom #define rte_bit_atomic_test(addr, nr, memory_order) \ 26735326b61SMattias Rönnblom _Generic((addr), \ 26835326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_test32, \ 26935326b61SMattias Rönnblom const uint32_t *: __rte_bit_atomic_test32, \ 2700883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_test32, \ 2710883d736SMattias Rönnblom const volatile uint32_t *: __rte_bit_atomic_v_test32, \ 27235326b61SMattias Rönnblom uint64_t *: __rte_bit_atomic_test64, \ 2730883d736SMattias Rönnblom const uint64_t *: __rte_bit_atomic_test64, \ 2740883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_test64, \ 2750883d736SMattias Rönnblom const volatile uint64_t *: __rte_bit_atomic_v_test64) \ 27635326b61SMattias Rönnblom (addr, nr, memory_order) 27735326b61SMattias Rönnblom 27835326b61SMattias Rönnblom /** 27935326b61SMattias Rönnblom * @warning 28035326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 28135326b61SMattias Rönnblom * 28235326b61SMattias Rönnblom * Atomically set bit in word. 28335326b61SMattias Rönnblom * 28435326b61SMattias Rönnblom * Generic selection macro to atomically set bit specified by @c nr in 28535326b61SMattias Rönnblom * the word pointed to by @c addr to '1', with the memory ordering as 28635326b61SMattias Rönnblom * specified by @c memory_order. 28735326b61SMattias Rönnblom * 28835326b61SMattias Rönnblom * @param addr 28935326b61SMattias Rönnblom * A pointer to the word to modify. 29035326b61SMattias Rönnblom * @param nr 29135326b61SMattias Rönnblom * The index of the bit. 29235326b61SMattias Rönnblom * @param memory_order 29335326b61SMattias Rönnblom * The memory order to use. 29435326b61SMattias Rönnblom */ 29535326b61SMattias Rönnblom #define rte_bit_atomic_set(addr, nr, memory_order) \ 29635326b61SMattias Rönnblom _Generic((addr), \ 29735326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_set32, \ 2980883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_set32, \ 2990883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_set64, \ 3000883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_set64) \ 30135326b61SMattias Rönnblom (addr, nr, memory_order) 30235326b61SMattias Rönnblom 30335326b61SMattias Rönnblom /** 30435326b61SMattias Rönnblom * @warning 30535326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 30635326b61SMattias Rönnblom * 30735326b61SMattias Rönnblom * Atomically clear bit in word. 30835326b61SMattias Rönnblom * 30935326b61SMattias Rönnblom * Generic selection macro to atomically set bit specified by @c nr in 31035326b61SMattias Rönnblom * the word pointed to by @c addr to '0', with the memory ordering as 31135326b61SMattias Rönnblom * specified by @c memory_order. 31235326b61SMattias Rönnblom * 31335326b61SMattias Rönnblom * @param addr 31435326b61SMattias Rönnblom * A pointer to the word to modify. 31535326b61SMattias Rönnblom * @param nr 31635326b61SMattias Rönnblom * The index of the bit. 31735326b61SMattias Rönnblom * @param memory_order 31835326b61SMattias Rönnblom * The memory order to use. 31935326b61SMattias Rönnblom */ 32035326b61SMattias Rönnblom #define rte_bit_atomic_clear(addr, nr, memory_order) \ 32135326b61SMattias Rönnblom _Generic((addr), \ 32235326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_clear32, \ 3230883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_clear32, \ 3240883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_clear64, \ 3250883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_clear64) \ 32635326b61SMattias Rönnblom (addr, nr, memory_order) 32735326b61SMattias Rönnblom 32835326b61SMattias Rönnblom /** 32935326b61SMattias Rönnblom * @warning 33035326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 33135326b61SMattias Rönnblom * 33235326b61SMattias Rönnblom * Atomically assign a value to bit in word. 33335326b61SMattias Rönnblom * 33435326b61SMattias Rönnblom * Generic selection macro to atomically set bit specified by @c nr in the 33535326b61SMattias Rönnblom * word pointed to by @c addr to the value indicated by @c value, with 33635326b61SMattias Rönnblom * the memory ordering as specified with @c memory_order. 33735326b61SMattias Rönnblom * 33835326b61SMattias Rönnblom * @param addr 33935326b61SMattias Rönnblom * A pointer to the word to modify. 34035326b61SMattias Rönnblom * @param nr 34135326b61SMattias Rönnblom * The index of the bit. 34235326b61SMattias Rönnblom * @param value 34335326b61SMattias Rönnblom * The new value of the bit - true for '1', or false for '0'. 34435326b61SMattias Rönnblom * @param memory_order 34535326b61SMattias Rönnblom * The memory order to use. 34635326b61SMattias Rönnblom */ 34735326b61SMattias Rönnblom #define rte_bit_atomic_assign(addr, nr, value, memory_order) \ 34835326b61SMattias Rönnblom _Generic((addr), \ 34935326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_assign32, \ 3500883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_assign32, \ 3510883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_assign64, \ 3520883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_assign64) \ 35335326b61SMattias Rönnblom (addr, nr, value, memory_order) 35435326b61SMattias Rönnblom 35535326b61SMattias Rönnblom /** 35635326b61SMattias Rönnblom * @warning 35735326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 35835326b61SMattias Rönnblom * 35935326b61SMattias Rönnblom * Atomically flip bit in word. 36035326b61SMattias Rönnblom * 36135326b61SMattias Rönnblom * Generic selection macro to atomically negate the value of the bit 36235326b61SMattias Rönnblom * specified by @c nr in the word pointed to by @c addr to the value 36335326b61SMattias Rönnblom * indicated by @c value, with the memory ordering as specified with 36435326b61SMattias Rönnblom * @c memory_order. 36535326b61SMattias Rönnblom * 36635326b61SMattias Rönnblom * @param addr 36735326b61SMattias Rönnblom * A pointer to the word to modify. 36835326b61SMattias Rönnblom * @param nr 36935326b61SMattias Rönnblom * The index of the bit. 37035326b61SMattias Rönnblom * @param memory_order 37135326b61SMattias Rönnblom * The memory order to use. 37235326b61SMattias Rönnblom */ 37335326b61SMattias Rönnblom #define rte_bit_atomic_flip(addr, nr, memory_order) \ 37435326b61SMattias Rönnblom _Generic((addr), \ 37535326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_flip32, \ 3760883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_flip32, \ 3770883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_flip64, \ 3780883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_flip64) \ 37935326b61SMattias Rönnblom (addr, nr, memory_order) 38035326b61SMattias Rönnblom 38135326b61SMattias Rönnblom /** 38235326b61SMattias Rönnblom * @warning 38335326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 38435326b61SMattias Rönnblom * 38535326b61SMattias Rönnblom * Atomically test and set a bit in word. 38635326b61SMattias Rönnblom * 38735326b61SMattias Rönnblom * Generic selection macro to atomically test and set bit specified by 38835326b61SMattias Rönnblom * @c nr in the word pointed to by @c addr to '1', with the memory 38935326b61SMattias Rönnblom * ordering as specified with @c memory_order. 39035326b61SMattias Rönnblom * 39135326b61SMattias Rönnblom * @param addr 39235326b61SMattias Rönnblom * A pointer to the word to modify. 39335326b61SMattias Rönnblom * @param nr 39435326b61SMattias Rönnblom * The index of the bit. 39535326b61SMattias Rönnblom * @param memory_order 39635326b61SMattias Rönnblom * The memory order to use. 39735326b61SMattias Rönnblom * @return 39835326b61SMattias Rönnblom * Returns true if the bit was set, and false otherwise. 39935326b61SMattias Rönnblom */ 40035326b61SMattias Rönnblom #define rte_bit_atomic_test_and_set(addr, nr, memory_order) \ 40135326b61SMattias Rönnblom _Generic((addr), \ 40235326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_test_and_set32, \ 4030883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_test_and_set32, \ 4040883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_test_and_set64, \ 4050883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_test_and_set64) \ 40635326b61SMattias Rönnblom (addr, nr, memory_order) 40735326b61SMattias Rönnblom 40835326b61SMattias Rönnblom /** 40935326b61SMattias Rönnblom * @warning 41035326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 41135326b61SMattias Rönnblom * 41235326b61SMattias Rönnblom * Atomically test and clear a bit in word. 41335326b61SMattias Rönnblom * 41435326b61SMattias Rönnblom * Generic selection macro to atomically test and clear bit specified 41535326b61SMattias Rönnblom * by @c nr in the word pointed to by @c addr to '0', with the memory 41635326b61SMattias Rönnblom * ordering as specified with @c memory_order. 41735326b61SMattias Rönnblom * 41835326b61SMattias Rönnblom * @param addr 41935326b61SMattias Rönnblom * A pointer to the word to modify. 42035326b61SMattias Rönnblom * @param nr 42135326b61SMattias Rönnblom * The index of the bit. 42235326b61SMattias Rönnblom * @param memory_order 42335326b61SMattias Rönnblom * The memory order to use. 42435326b61SMattias Rönnblom * @return 42535326b61SMattias Rönnblom * Returns true if the bit was set, and false otherwise. 42635326b61SMattias Rönnblom */ 42735326b61SMattias Rönnblom #define rte_bit_atomic_test_and_clear(addr, nr, memory_order) \ 42835326b61SMattias Rönnblom _Generic((addr), \ 42935326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_test_and_clear32, \ 4300883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_test_and_clear32, \ 4310883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_test_and_clear64, \ 4320883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_test_and_clear64) \ 43335326b61SMattias Rönnblom (addr, nr, memory_order) 43435326b61SMattias Rönnblom 43535326b61SMattias Rönnblom /** 43635326b61SMattias Rönnblom * @warning 43735326b61SMattias Rönnblom * @b EXPERIMENTAL: this API may change without prior notice. 43835326b61SMattias Rönnblom * 43935326b61SMattias Rönnblom * Atomically test and assign a bit in word. 44035326b61SMattias Rönnblom * 44135326b61SMattias Rönnblom * Generic selection macro to atomically test and assign bit specified 44235326b61SMattias Rönnblom * by @c nr in the word pointed to by @c addr the value specified by 44335326b61SMattias Rönnblom * @c value, with the memory ordering as specified with @c 44435326b61SMattias Rönnblom * memory_order. 44535326b61SMattias Rönnblom * 44635326b61SMattias Rönnblom * @param addr 44735326b61SMattias Rönnblom * A pointer to the word to modify. 44835326b61SMattias Rönnblom * @param nr 44935326b61SMattias Rönnblom * The index of the bit. 45035326b61SMattias Rönnblom * @param value 45135326b61SMattias Rönnblom * The new value of the bit - true for '1', or false for '0'. 45235326b61SMattias Rönnblom * @param memory_order 45335326b61SMattias Rönnblom * The memory order to use. 45435326b61SMattias Rönnblom * @return 45535326b61SMattias Rönnblom * Returns true if the bit was set, and false otherwise. 45635326b61SMattias Rönnblom */ 45735326b61SMattias Rönnblom #define rte_bit_atomic_test_and_assign(addr, nr, value, memory_order) \ 45835326b61SMattias Rönnblom _Generic((addr), \ 45935326b61SMattias Rönnblom uint32_t *: __rte_bit_atomic_test_and_assign32, \ 4600883d736SMattias Rönnblom volatile uint32_t *: __rte_bit_atomic_v_test_and_assign32, \ 4610883d736SMattias Rönnblom uint64_t *: __rte_bit_atomic_test_and_assign64, \ 4620883d736SMattias Rönnblom volatile uint64_t *: __rte_bit_atomic_v_test_and_assign64) \ 46335326b61SMattias Rönnblom (addr, nr, value, memory_order) 46435326b61SMattias Rönnblom 465471de107SMattias Rönnblom #define __RTE_GEN_BIT_TEST(variant, qualifier, size) \ 466471de107SMattias Rönnblom __rte_experimental \ 467471de107SMattias Rönnblom static inline bool \ 468471de107SMattias Rönnblom __rte_bit_ ## variant ## test ## size(const qualifier uint ## size ## _t *addr, unsigned int nr) \ 469471de107SMattias Rönnblom { \ 470471de107SMattias Rönnblom RTE_ASSERT(nr < size); \ 471471de107SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 472471de107SMattias Rönnblom return *addr & mask; \ 473471de107SMattias Rönnblom } 474471de107SMattias Rönnblom 475471de107SMattias Rönnblom #define __RTE_GEN_BIT_SET(variant, qualifier, size) \ 476471de107SMattias Rönnblom __rte_experimental \ 477471de107SMattias Rönnblom static inline void \ 478471de107SMattias Rönnblom __rte_bit_ ## variant ## set ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \ 479471de107SMattias Rönnblom { \ 480471de107SMattias Rönnblom RTE_ASSERT(nr < size); \ 481471de107SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 482471de107SMattias Rönnblom *addr |= mask; \ 483471de107SMattias Rönnblom } 484471de107SMattias Rönnblom 485471de107SMattias Rönnblom #define __RTE_GEN_BIT_CLEAR(variant, qualifier, size) \ 486471de107SMattias Rönnblom __rte_experimental \ 487471de107SMattias Rönnblom static inline void \ 488471de107SMattias Rönnblom __rte_bit_ ## variant ## clear ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \ 489471de107SMattias Rönnblom { \ 490471de107SMattias Rönnblom RTE_ASSERT(nr < size); \ 491471de107SMattias Rönnblom uint ## size ## _t mask = ~((uint ## size ## _t)1 << nr); \ 492471de107SMattias Rönnblom (*addr) &= mask; \ 493471de107SMattias Rönnblom } 494471de107SMattias Rönnblom 495471de107SMattias Rönnblom #define __RTE_GEN_BIT_ASSIGN(variant, qualifier, size) \ 496471de107SMattias Rönnblom __rte_experimental \ 497471de107SMattias Rönnblom static inline void \ 498471de107SMattias Rönnblom __rte_bit_ ## variant ## assign ## size(qualifier uint ## size ## _t *addr, unsigned int nr, \ 499471de107SMattias Rönnblom bool value) \ 500471de107SMattias Rönnblom { \ 501471de107SMattias Rönnblom if (value) \ 502471de107SMattias Rönnblom __rte_bit_ ## variant ## set ## size(addr, nr); \ 503471de107SMattias Rönnblom else \ 504471de107SMattias Rönnblom __rte_bit_ ## variant ## clear ## size(addr, nr); \ 505471de107SMattias Rönnblom } 506471de107SMattias Rönnblom 507471de107SMattias Rönnblom #define __RTE_GEN_BIT_FLIP(variant, qualifier, size) \ 508471de107SMattias Rönnblom __rte_experimental \ 509471de107SMattias Rönnblom static inline void \ 510471de107SMattias Rönnblom __rte_bit_ ## variant ## flip ## size(qualifier uint ## size ## _t *addr, unsigned int nr) \ 511471de107SMattias Rönnblom { \ 512471de107SMattias Rönnblom bool value; \ 513471de107SMattias Rönnblom value = __rte_bit_ ## variant ## test ## size(addr, nr); \ 514471de107SMattias Rönnblom __rte_bit_ ## variant ## assign ## size(addr, nr, !value); \ 515471de107SMattias Rönnblom } 516471de107SMattias Rönnblom 517471de107SMattias Rönnblom #define __RTE_GEN_BIT_OPS(v, qualifier, size) \ 518471de107SMattias Rönnblom __RTE_GEN_BIT_TEST(v, qualifier, size) \ 519471de107SMattias Rönnblom __RTE_GEN_BIT_SET(v, qualifier, size) \ 520471de107SMattias Rönnblom __RTE_GEN_BIT_CLEAR(v, qualifier, size) \ 521471de107SMattias Rönnblom __RTE_GEN_BIT_ASSIGN(v, qualifier, size) \ 522471de107SMattias Rönnblom __RTE_GEN_BIT_FLIP(v, qualifier, size) 523471de107SMattias Rönnblom 524471de107SMattias Rönnblom #define __RTE_GEN_BIT_OPS_SIZE(size) \ 5250883d736SMattias Rönnblom __RTE_GEN_BIT_OPS(,, size) \ 5260883d736SMattias Rönnblom __RTE_GEN_BIT_OPS(v_, volatile, size) 527471de107SMattias Rönnblom 5288b65ddc0SDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API 529471de107SMattias Rönnblom __RTE_GEN_BIT_OPS_SIZE(32) 530471de107SMattias Rönnblom __RTE_GEN_BIT_OPS_SIZE(64) 5318b65ddc0SDavid Marchand #endif 532471de107SMattias Rönnblom 53335326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST(variant, qualifier, size) \ 53435326b61SMattias Rönnblom __rte_experimental \ 53535326b61SMattias Rönnblom static inline bool \ 53635326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test ## size(const qualifier uint ## size ## _t *addr, \ 53735326b61SMattias Rönnblom unsigned int nr, int memory_order) \ 53835326b61SMattias Rönnblom { \ 53935326b61SMattias Rönnblom RTE_ASSERT(nr < size); \ 54035326b61SMattias Rönnblom const qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \ 54135326b61SMattias Rönnblom (const qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \ 54235326b61SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 54335326b61SMattias Rönnblom return rte_atomic_load_explicit(a_addr, memory_order) & mask; \ 54435326b61SMattias Rönnblom } 54535326b61SMattias Rönnblom 54635326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_SET(variant, qualifier, size) \ 54735326b61SMattias Rönnblom __rte_experimental \ 54835326b61SMattias Rönnblom static inline void \ 54935326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## set ## size(qualifier uint ## size ## _t *addr, \ 55035326b61SMattias Rönnblom unsigned int nr, int memory_order) \ 55135326b61SMattias Rönnblom { \ 55235326b61SMattias Rönnblom RTE_ASSERT(nr < size); \ 55335326b61SMattias Rönnblom qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \ 55435326b61SMattias Rönnblom (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \ 55535326b61SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 55635326b61SMattias Rönnblom rte_atomic_fetch_or_explicit(a_addr, mask, memory_order); \ 55735326b61SMattias Rönnblom } 55835326b61SMattias Rönnblom 55935326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_CLEAR(variant, qualifier, size) \ 56035326b61SMattias Rönnblom __rte_experimental \ 56135326b61SMattias Rönnblom static inline void \ 56235326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## clear ## size(qualifier uint ## size ## _t *addr, \ 56335326b61SMattias Rönnblom unsigned int nr, int memory_order) \ 56435326b61SMattias Rönnblom { \ 56535326b61SMattias Rönnblom RTE_ASSERT(nr < size); \ 56635326b61SMattias Rönnblom qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \ 56735326b61SMattias Rönnblom (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \ 56835326b61SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 56935326b61SMattias Rönnblom rte_atomic_fetch_and_explicit(a_addr, ~mask, memory_order); \ 57035326b61SMattias Rönnblom } 57135326b61SMattias Rönnblom 57235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_FLIP(variant, qualifier, size) \ 57335326b61SMattias Rönnblom __rte_experimental \ 57435326b61SMattias Rönnblom static inline void \ 57535326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## flip ## size(qualifier uint ## size ## _t *addr, \ 57635326b61SMattias Rönnblom unsigned int nr, int memory_order) \ 57735326b61SMattias Rönnblom { \ 57835326b61SMattias Rönnblom RTE_ASSERT(nr < size); \ 57935326b61SMattias Rönnblom qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \ 58035326b61SMattias Rönnblom (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \ 58135326b61SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 58235326b61SMattias Rönnblom rte_atomic_fetch_xor_explicit(a_addr, mask, memory_order); \ 58335326b61SMattias Rönnblom } 58435326b61SMattias Rönnblom 58535326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_ASSIGN(variant, qualifier, size) \ 58635326b61SMattias Rönnblom __rte_experimental \ 58735326b61SMattias Rönnblom static inline void \ 58835326b61SMattias Rönnblom __rte_bit_atomic_## variant ## assign ## size(qualifier uint ## size ## _t *addr, \ 58935326b61SMattias Rönnblom unsigned int nr, bool value, int memory_order) \ 59035326b61SMattias Rönnblom { \ 59135326b61SMattias Rönnblom if (value) \ 59235326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## set ## size(addr, nr, memory_order); \ 59335326b61SMattias Rönnblom else \ 59435326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## clear ## size(addr, nr, memory_order); \ 59535326b61SMattias Rönnblom } 59635326b61SMattias Rönnblom 59735326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST_AND_SET(variant, qualifier, size) \ 59835326b61SMattias Rönnblom __rte_experimental \ 59935326b61SMattias Rönnblom static inline bool \ 60035326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test_and_set ## size(qualifier uint ## size ## _t *addr, \ 60135326b61SMattias Rönnblom unsigned int nr, int memory_order) \ 60235326b61SMattias Rönnblom { \ 60335326b61SMattias Rönnblom RTE_ASSERT(nr < size); \ 60435326b61SMattias Rönnblom qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \ 60535326b61SMattias Rönnblom (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \ 60635326b61SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 60735326b61SMattias Rönnblom uint ## size ## _t prev; \ 60835326b61SMattias Rönnblom prev = rte_atomic_fetch_or_explicit(a_addr, mask, memory_order); \ 60935326b61SMattias Rönnblom return prev & mask; \ 61035326b61SMattias Rönnblom } 61135326b61SMattias Rönnblom 61235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST_AND_CLEAR(variant, qualifier, size) \ 61335326b61SMattias Rönnblom __rte_experimental \ 61435326b61SMattias Rönnblom static inline bool \ 61535326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test_and_clear ## size(qualifier uint ## size ## _t *addr, \ 61635326b61SMattias Rönnblom unsigned int nr, int memory_order) \ 61735326b61SMattias Rönnblom { \ 61835326b61SMattias Rönnblom RTE_ASSERT(nr < size); \ 61935326b61SMattias Rönnblom qualifier RTE_ATOMIC(uint ## size ## _t) *a_addr = \ 62035326b61SMattias Rönnblom (qualifier RTE_ATOMIC(uint ## size ## _t) *)addr; \ 62135326b61SMattias Rönnblom uint ## size ## _t mask = (uint ## size ## _t)1 << nr; \ 62235326b61SMattias Rönnblom uint ## size ## _t prev; \ 62335326b61SMattias Rönnblom prev = rte_atomic_fetch_and_explicit(a_addr, ~mask, memory_order); \ 62435326b61SMattias Rönnblom return prev & mask; \ 62535326b61SMattias Rönnblom } 62635326b61SMattias Rönnblom 62735326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_TEST_AND_ASSIGN(variant, qualifier, size) \ 62835326b61SMattias Rönnblom __rte_experimental \ 62935326b61SMattias Rönnblom static inline bool \ 63035326b61SMattias Rönnblom __rte_bit_atomic_ ## variant ## test_and_assign ## size( \ 63135326b61SMattias Rönnblom qualifier uint ## size ## _t *addr, unsigned int nr, bool value, \ 63235326b61SMattias Rönnblom int memory_order) \ 63335326b61SMattias Rönnblom { \ 63435326b61SMattias Rönnblom if (value) \ 63535326b61SMattias Rönnblom return __rte_bit_atomic_ ## variant ## test_and_set ## size(addr, nr, \ 63635326b61SMattias Rönnblom memory_order); \ 63735326b61SMattias Rönnblom else \ 63835326b61SMattias Rönnblom return __rte_bit_atomic_ ## variant ## test_and_clear ## size(addr, nr, \ 63935326b61SMattias Rönnblom memory_order); \ 64035326b61SMattias Rönnblom } 64135326b61SMattias Rönnblom 64235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_OPS(variant, qualifier, size) \ 64335326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_TEST(variant, qualifier, size) \ 64435326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_SET(variant, qualifier, size) \ 64535326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_CLEAR(variant, qualifier, size) \ 64635326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_ASSIGN(variant, qualifier, size) \ 64735326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_TEST_AND_SET(variant, qualifier, size) \ 64835326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_TEST_AND_CLEAR(variant, qualifier, size) \ 64935326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_TEST_AND_ASSIGN(variant, qualifier, size) \ 65035326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_FLIP(variant, qualifier, size) 65135326b61SMattias Rönnblom 65235326b61SMattias Rönnblom #define __RTE_GEN_BIT_ATOMIC_OPS_SIZE(size) \ 6530883d736SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_OPS(,, size) \ 6540883d736SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_OPS(v_, volatile, size) 65535326b61SMattias Rönnblom 6568b65ddc0SDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API 65735326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_OPS_SIZE(32) 65835326b61SMattias Rönnblom __RTE_GEN_BIT_ATOMIC_OPS_SIZE(64) 6598b65ddc0SDavid Marchand #endif 66035326b61SMattias Rönnblom 66199a2dd95SBruce Richardson /*------------------------ 32-bit relaxed operations ------------------------*/ 66299a2dd95SBruce Richardson 66399a2dd95SBruce Richardson /** 66499a2dd95SBruce Richardson * Get the target bit from a 32-bit value without memory ordering. 66599a2dd95SBruce Richardson * 66699a2dd95SBruce Richardson * @param nr 66799a2dd95SBruce Richardson * The target bit to get. 66899a2dd95SBruce Richardson * @param addr 66999a2dd95SBruce Richardson * The address holding the bit. 67099a2dd95SBruce Richardson * @return 67199a2dd95SBruce Richardson * The target bit. 67299a2dd95SBruce Richardson */ 67399a2dd95SBruce Richardson static inline uint32_t 67499a2dd95SBruce Richardson rte_bit_relaxed_get32(unsigned int nr, volatile uint32_t *addr) 67599a2dd95SBruce Richardson { 67699a2dd95SBruce Richardson RTE_ASSERT(nr < 32); 67799a2dd95SBruce Richardson 67899a2dd95SBruce Richardson uint32_t mask = UINT32_C(1) << nr; 67999a2dd95SBruce Richardson return (*addr) & mask; 68099a2dd95SBruce Richardson } 68199a2dd95SBruce Richardson 68299a2dd95SBruce Richardson /** 68399a2dd95SBruce Richardson * Set the target bit in a 32-bit value to 1 without memory ordering. 68499a2dd95SBruce Richardson * 68599a2dd95SBruce Richardson * @param nr 68699a2dd95SBruce Richardson * The target bit to set. 68799a2dd95SBruce Richardson * @param addr 68899a2dd95SBruce Richardson * The address holding the bit. 68999a2dd95SBruce Richardson */ 69099a2dd95SBruce Richardson static inline void 69199a2dd95SBruce Richardson rte_bit_relaxed_set32(unsigned int nr, volatile uint32_t *addr) 69299a2dd95SBruce Richardson { 69399a2dd95SBruce Richardson RTE_ASSERT(nr < 32); 69499a2dd95SBruce Richardson 69599a2dd95SBruce Richardson uint32_t mask = RTE_BIT32(nr); 69699a2dd95SBruce Richardson *addr = (*addr) | mask; 69799a2dd95SBruce Richardson } 69899a2dd95SBruce Richardson 69999a2dd95SBruce Richardson /** 70099a2dd95SBruce Richardson * Clear the target bit in a 32-bit value to 0 without memory ordering. 70199a2dd95SBruce Richardson * 70299a2dd95SBruce Richardson * @param nr 70399a2dd95SBruce Richardson * The target bit to clear. 70499a2dd95SBruce Richardson * @param addr 70599a2dd95SBruce Richardson * The address holding the bit. 70699a2dd95SBruce Richardson */ 70799a2dd95SBruce Richardson static inline void 70899a2dd95SBruce Richardson rte_bit_relaxed_clear32(unsigned int nr, volatile uint32_t *addr) 70999a2dd95SBruce Richardson { 71099a2dd95SBruce Richardson RTE_ASSERT(nr < 32); 71199a2dd95SBruce Richardson 71299a2dd95SBruce Richardson uint32_t mask = RTE_BIT32(nr); 71399a2dd95SBruce Richardson *addr = (*addr) & (~mask); 71499a2dd95SBruce Richardson } 71599a2dd95SBruce Richardson 71699a2dd95SBruce Richardson /** 71799a2dd95SBruce Richardson * Return the original bit from a 32-bit value, then set it to 1 without 71899a2dd95SBruce Richardson * memory ordering. 71999a2dd95SBruce Richardson * 72099a2dd95SBruce Richardson * @param nr 72199a2dd95SBruce Richardson * The target bit to get and set. 72299a2dd95SBruce Richardson * @param addr 72399a2dd95SBruce Richardson * The address holding the bit. 72499a2dd95SBruce Richardson * @return 72599a2dd95SBruce Richardson * The original bit. 72699a2dd95SBruce Richardson */ 72799a2dd95SBruce Richardson static inline uint32_t 72899a2dd95SBruce Richardson rte_bit_relaxed_test_and_set32(unsigned int nr, volatile uint32_t *addr) 72999a2dd95SBruce Richardson { 73099a2dd95SBruce Richardson RTE_ASSERT(nr < 32); 73199a2dd95SBruce Richardson 73299a2dd95SBruce Richardson uint32_t mask = RTE_BIT32(nr); 73399a2dd95SBruce Richardson uint32_t val = *addr; 73499a2dd95SBruce Richardson *addr = val | mask; 73599a2dd95SBruce Richardson return val & mask; 73699a2dd95SBruce Richardson } 73799a2dd95SBruce Richardson 73899a2dd95SBruce Richardson /** 73999a2dd95SBruce Richardson * Return the original bit from a 32-bit value, then clear it to 0 without 74099a2dd95SBruce Richardson * memory ordering. 74199a2dd95SBruce Richardson * 74299a2dd95SBruce Richardson * @param nr 74399a2dd95SBruce Richardson * The target bit to get and clear. 74499a2dd95SBruce Richardson * @param addr 74599a2dd95SBruce Richardson * The address holding the bit. 74699a2dd95SBruce Richardson * @return 74799a2dd95SBruce Richardson * The original bit. 74899a2dd95SBruce Richardson */ 74999a2dd95SBruce Richardson static inline uint32_t 75099a2dd95SBruce Richardson rte_bit_relaxed_test_and_clear32(unsigned int nr, volatile uint32_t *addr) 75199a2dd95SBruce Richardson { 75299a2dd95SBruce Richardson RTE_ASSERT(nr < 32); 75399a2dd95SBruce Richardson 75499a2dd95SBruce Richardson uint32_t mask = RTE_BIT32(nr); 75599a2dd95SBruce Richardson uint32_t val = *addr; 75699a2dd95SBruce Richardson *addr = val & (~mask); 75799a2dd95SBruce Richardson return val & mask; 75899a2dd95SBruce Richardson } 75999a2dd95SBruce Richardson 76099a2dd95SBruce Richardson /*------------------------ 64-bit relaxed operations ------------------------*/ 76199a2dd95SBruce Richardson 76299a2dd95SBruce Richardson /** 76399a2dd95SBruce Richardson * Get the target bit from a 64-bit value without memory ordering. 76499a2dd95SBruce Richardson * 76599a2dd95SBruce Richardson * @param nr 76699a2dd95SBruce Richardson * The target bit to get. 76799a2dd95SBruce Richardson * @param addr 76899a2dd95SBruce Richardson * The address holding the bit. 76999a2dd95SBruce Richardson * @return 77099a2dd95SBruce Richardson * The target bit. 77199a2dd95SBruce Richardson */ 77299a2dd95SBruce Richardson static inline uint64_t 77399a2dd95SBruce Richardson rte_bit_relaxed_get64(unsigned int nr, volatile uint64_t *addr) 77499a2dd95SBruce Richardson { 77599a2dd95SBruce Richardson RTE_ASSERT(nr < 64); 77699a2dd95SBruce Richardson 77799a2dd95SBruce Richardson uint64_t mask = RTE_BIT64(nr); 77899a2dd95SBruce Richardson return (*addr) & mask; 77999a2dd95SBruce Richardson } 78099a2dd95SBruce Richardson 78199a2dd95SBruce Richardson /** 78299a2dd95SBruce Richardson * Set the target bit in a 64-bit value to 1 without memory ordering. 78399a2dd95SBruce Richardson * 78499a2dd95SBruce Richardson * @param nr 78599a2dd95SBruce Richardson * The target bit to set. 78699a2dd95SBruce Richardson * @param addr 78799a2dd95SBruce Richardson * The address holding the bit. 78899a2dd95SBruce Richardson */ 78999a2dd95SBruce Richardson static inline void 79099a2dd95SBruce Richardson rte_bit_relaxed_set64(unsigned int nr, volatile uint64_t *addr) 79199a2dd95SBruce Richardson { 79299a2dd95SBruce Richardson RTE_ASSERT(nr < 64); 79399a2dd95SBruce Richardson 79499a2dd95SBruce Richardson uint64_t mask = RTE_BIT64(nr); 79599a2dd95SBruce Richardson (*addr) = (*addr) | mask; 79699a2dd95SBruce Richardson } 79799a2dd95SBruce Richardson 79899a2dd95SBruce Richardson /** 79999a2dd95SBruce Richardson * Clear the target bit in a 64-bit value to 0 without memory ordering. 80099a2dd95SBruce Richardson * 80199a2dd95SBruce Richardson * @param nr 80299a2dd95SBruce Richardson * The target bit to clear. 80399a2dd95SBruce Richardson * @param addr 80499a2dd95SBruce Richardson * The address holding the bit. 80599a2dd95SBruce Richardson */ 80699a2dd95SBruce Richardson static inline void 80799a2dd95SBruce Richardson rte_bit_relaxed_clear64(unsigned int nr, volatile uint64_t *addr) 80899a2dd95SBruce Richardson { 80999a2dd95SBruce Richardson RTE_ASSERT(nr < 64); 81099a2dd95SBruce Richardson 81199a2dd95SBruce Richardson uint64_t mask = RTE_BIT64(nr); 81299a2dd95SBruce Richardson *addr = (*addr) & (~mask); 81399a2dd95SBruce Richardson } 81499a2dd95SBruce Richardson 81599a2dd95SBruce Richardson /** 81699a2dd95SBruce Richardson * Return the original bit from a 64-bit value, then set it to 1 without 81799a2dd95SBruce Richardson * memory ordering. 81899a2dd95SBruce Richardson * 81999a2dd95SBruce Richardson * @param nr 82099a2dd95SBruce Richardson * The target bit to get and set. 82199a2dd95SBruce Richardson * @param addr 82299a2dd95SBruce Richardson * The address holding the bit. 82399a2dd95SBruce Richardson * @return 82499a2dd95SBruce Richardson * The original bit. 82599a2dd95SBruce Richardson */ 82699a2dd95SBruce Richardson static inline uint64_t 82799a2dd95SBruce Richardson rte_bit_relaxed_test_and_set64(unsigned int nr, volatile uint64_t *addr) 82899a2dd95SBruce Richardson { 82999a2dd95SBruce Richardson RTE_ASSERT(nr < 64); 83099a2dd95SBruce Richardson 83199a2dd95SBruce Richardson uint64_t mask = RTE_BIT64(nr); 83299a2dd95SBruce Richardson uint64_t val = *addr; 83399a2dd95SBruce Richardson *addr = val | mask; 83499a2dd95SBruce Richardson return val; 83599a2dd95SBruce Richardson } 83699a2dd95SBruce Richardson 83799a2dd95SBruce Richardson /** 83899a2dd95SBruce Richardson * Return the original bit from a 64-bit value, then clear it to 0 without 83999a2dd95SBruce Richardson * memory ordering. 84099a2dd95SBruce Richardson * 84199a2dd95SBruce Richardson * @param nr 84299a2dd95SBruce Richardson * The target bit to get and clear. 84399a2dd95SBruce Richardson * @param addr 84499a2dd95SBruce Richardson * The address holding the bit. 84599a2dd95SBruce Richardson * @return 84699a2dd95SBruce Richardson * The original bit. 84799a2dd95SBruce Richardson */ 84899a2dd95SBruce Richardson static inline uint64_t 84999a2dd95SBruce Richardson rte_bit_relaxed_test_and_clear64(unsigned int nr, volatile uint64_t *addr) 85099a2dd95SBruce Richardson { 85199a2dd95SBruce Richardson RTE_ASSERT(nr < 64); 85299a2dd95SBruce Richardson 85399a2dd95SBruce Richardson uint64_t mask = RTE_BIT64(nr); 85499a2dd95SBruce Richardson uint64_t val = *addr; 85599a2dd95SBruce Richardson *addr = val & (~mask); 85699a2dd95SBruce Richardson return val & mask; 85799a2dd95SBruce Richardson } 85899a2dd95SBruce Richardson 859916c50ddSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC 860916c50ddSTyler Retzlaff 861916c50ddSTyler Retzlaff /** 862916c50ddSTyler Retzlaff * Get the count of leading 0-bits in v. 863916c50ddSTyler Retzlaff * 864916c50ddSTyler Retzlaff * @param v 865916c50ddSTyler Retzlaff * The value. 866916c50ddSTyler Retzlaff * @return 867916c50ddSTyler Retzlaff * The count of leading zero bits. 868916c50ddSTyler Retzlaff */ 869916c50ddSTyler Retzlaff static inline unsigned int 870916c50ddSTyler Retzlaff rte_clz32(uint32_t v) 871916c50ddSTyler Retzlaff { 872916c50ddSTyler Retzlaff unsigned long rv; 873916c50ddSTyler Retzlaff 874916c50ddSTyler Retzlaff (void)_BitScanReverse(&rv, v); 875916c50ddSTyler Retzlaff 876916c50ddSTyler Retzlaff return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv); 877916c50ddSTyler Retzlaff } 878916c50ddSTyler Retzlaff 879916c50ddSTyler Retzlaff /** 880916c50ddSTyler Retzlaff * Get the count of leading 0-bits in v. 881916c50ddSTyler Retzlaff * 882916c50ddSTyler Retzlaff * @param v 883916c50ddSTyler Retzlaff * The value. 884916c50ddSTyler Retzlaff * @return 885916c50ddSTyler Retzlaff * The count of leading zero bits. 886916c50ddSTyler Retzlaff */ 887916c50ddSTyler Retzlaff static inline unsigned int 888916c50ddSTyler Retzlaff rte_clz64(uint64_t v) 889916c50ddSTyler Retzlaff { 890916c50ddSTyler Retzlaff unsigned long rv; 891916c50ddSTyler Retzlaff 892916c50ddSTyler Retzlaff (void)_BitScanReverse64(&rv, v); 893916c50ddSTyler Retzlaff 894916c50ddSTyler Retzlaff return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv); 895916c50ddSTyler Retzlaff } 896916c50ddSTyler Retzlaff 897916c50ddSTyler Retzlaff /** 898916c50ddSTyler Retzlaff * Get the count of trailing 0-bits in v. 899916c50ddSTyler Retzlaff * 900916c50ddSTyler Retzlaff * @param v 901916c50ddSTyler Retzlaff * The value. 902916c50ddSTyler Retzlaff * @return 903916c50ddSTyler Retzlaff * The count of trailing zero bits. 904916c50ddSTyler Retzlaff */ 905916c50ddSTyler Retzlaff static inline unsigned int 906916c50ddSTyler Retzlaff rte_ctz32(uint32_t v) 907916c50ddSTyler Retzlaff { 908916c50ddSTyler Retzlaff unsigned long rv; 909916c50ddSTyler Retzlaff 910916c50ddSTyler Retzlaff (void)_BitScanForward(&rv, v); 911916c50ddSTyler Retzlaff 912916c50ddSTyler Retzlaff return (unsigned int)rv; 913916c50ddSTyler Retzlaff } 914916c50ddSTyler Retzlaff 915916c50ddSTyler Retzlaff /** 916916c50ddSTyler Retzlaff * Get the count of trailing 0-bits in v. 917916c50ddSTyler Retzlaff * 918916c50ddSTyler Retzlaff * @param v 919916c50ddSTyler Retzlaff * The value. 920916c50ddSTyler Retzlaff * @return 921916c50ddSTyler Retzlaff * The count of trailing zero bits. 922916c50ddSTyler Retzlaff */ 923916c50ddSTyler Retzlaff static inline unsigned int 924916c50ddSTyler Retzlaff rte_ctz64(uint64_t v) 925916c50ddSTyler Retzlaff { 926916c50ddSTyler Retzlaff unsigned long rv; 927916c50ddSTyler Retzlaff 928916c50ddSTyler Retzlaff (void)_BitScanForward64(&rv, v); 929916c50ddSTyler Retzlaff 930916c50ddSTyler Retzlaff return (unsigned int)rv; 931916c50ddSTyler Retzlaff } 932916c50ddSTyler Retzlaff 933916c50ddSTyler Retzlaff /** 934916c50ddSTyler Retzlaff * Get the count of 1-bits in v. 935916c50ddSTyler Retzlaff * 936916c50ddSTyler Retzlaff * @param v 937916c50ddSTyler Retzlaff * The value. 938916c50ddSTyler Retzlaff * @return 939916c50ddSTyler Retzlaff * The count of 1-bits. 940916c50ddSTyler Retzlaff */ 941916c50ddSTyler Retzlaff static inline unsigned int 942916c50ddSTyler Retzlaff rte_popcount32(uint32_t v) 943916c50ddSTyler Retzlaff { 944916c50ddSTyler Retzlaff return (unsigned int)__popcnt(v); 945916c50ddSTyler Retzlaff } 946916c50ddSTyler Retzlaff 947916c50ddSTyler Retzlaff /** 948916c50ddSTyler Retzlaff * Get the count of 1-bits in v. 949916c50ddSTyler Retzlaff * 950916c50ddSTyler Retzlaff * @param v 951916c50ddSTyler Retzlaff * The value. 952916c50ddSTyler Retzlaff * @return 953916c50ddSTyler Retzlaff * The count of 1-bits. 954916c50ddSTyler Retzlaff */ 955916c50ddSTyler Retzlaff static inline unsigned int 956916c50ddSTyler Retzlaff rte_popcount64(uint64_t v) 957916c50ddSTyler Retzlaff { 958916c50ddSTyler Retzlaff return (unsigned int)__popcnt64(v); 959916c50ddSTyler Retzlaff } 960916c50ddSTyler Retzlaff 961*21cab84fSTyler Retzlaff /** 962*21cab84fSTyler Retzlaff * @warning 963*21cab84fSTyler Retzlaff * @b EXPERIMENTAL: this API may change without prior notice. 964*21cab84fSTyler Retzlaff * 965*21cab84fSTyler Retzlaff * Search v from least significant bit (LSB) to the most 966*21cab84fSTyler Retzlaff * significant bit (MSB) for a set bit (1). 967*21cab84fSTyler Retzlaff * 968*21cab84fSTyler Retzlaff * @param v 969*21cab84fSTyler Retzlaff * The value. 970*21cab84fSTyler Retzlaff * @return 971*21cab84fSTyler Retzlaff * Bit index + 1 if a set bit is found, zero otherwise. 972*21cab84fSTyler Retzlaff */ 973*21cab84fSTyler Retzlaff __rte_experimental 974*21cab84fSTyler Retzlaff static inline unsigned int 975*21cab84fSTyler Retzlaff rte_ffs32(uint32_t v) 976*21cab84fSTyler Retzlaff { 977*21cab84fSTyler Retzlaff unsigned long rv; 978*21cab84fSTyler Retzlaff 979*21cab84fSTyler Retzlaff if (_BitScanForward(&rv, v) == 0) 980*21cab84fSTyler Retzlaff return 0; 981*21cab84fSTyler Retzlaff 982*21cab84fSTyler Retzlaff return (unsigned int)rv + 1; 983*21cab84fSTyler Retzlaff } 984*21cab84fSTyler Retzlaff 985*21cab84fSTyler Retzlaff /** 986*21cab84fSTyler Retzlaff * @warning 987*21cab84fSTyler Retzlaff * @b EXPERIMENTAL: this API may change without prior notice. 988*21cab84fSTyler Retzlaff * 989*21cab84fSTyler Retzlaff * Search v from least significant bit (LSB) to the most 990*21cab84fSTyler Retzlaff * significant bit (MSB) for a set bit (1). 991*21cab84fSTyler Retzlaff * 992*21cab84fSTyler Retzlaff * @param v 993*21cab84fSTyler Retzlaff * The value. 994*21cab84fSTyler Retzlaff * @return 995*21cab84fSTyler Retzlaff * Bit index + 1 if a set bit is found, zero otherwise. 996*21cab84fSTyler Retzlaff */ 997*21cab84fSTyler Retzlaff __rte_experimental 998*21cab84fSTyler Retzlaff static inline unsigned int 999*21cab84fSTyler Retzlaff rte_ffs64(uint64_t v) 1000*21cab84fSTyler Retzlaff { 1001*21cab84fSTyler Retzlaff unsigned long rv; 1002*21cab84fSTyler Retzlaff 1003*21cab84fSTyler Retzlaff if (_BitScanForward64(&rv, v) == 0) 1004*21cab84fSTyler Retzlaff return 0; 1005*21cab84fSTyler Retzlaff 1006*21cab84fSTyler Retzlaff return (unsigned int)rv + 1; 1007*21cab84fSTyler Retzlaff } 1008*21cab84fSTyler Retzlaff 1009916c50ddSTyler Retzlaff #else 1010916c50ddSTyler Retzlaff 1011916c50ddSTyler Retzlaff /** 1012916c50ddSTyler Retzlaff * Get the count of leading 0-bits in v. 1013916c50ddSTyler Retzlaff * 1014916c50ddSTyler Retzlaff * @param v 1015916c50ddSTyler Retzlaff * The value. 1016916c50ddSTyler Retzlaff * @return 1017916c50ddSTyler Retzlaff * The count of leading zero bits. 1018916c50ddSTyler Retzlaff */ 1019916c50ddSTyler Retzlaff static inline unsigned int 1020916c50ddSTyler Retzlaff rte_clz32(uint32_t v) 1021916c50ddSTyler Retzlaff { 1022916c50ddSTyler Retzlaff return (unsigned int)__builtin_clz(v); 1023916c50ddSTyler Retzlaff } 1024916c50ddSTyler Retzlaff 1025916c50ddSTyler Retzlaff /** 1026916c50ddSTyler Retzlaff * Get the count of leading 0-bits in v. 1027916c50ddSTyler Retzlaff * 1028916c50ddSTyler Retzlaff * @param v 1029916c50ddSTyler Retzlaff * The value. 1030916c50ddSTyler Retzlaff * @return 1031916c50ddSTyler Retzlaff * The count of leading zero bits. 1032916c50ddSTyler Retzlaff */ 1033916c50ddSTyler Retzlaff static inline unsigned int 1034916c50ddSTyler Retzlaff rte_clz64(uint64_t v) 1035916c50ddSTyler Retzlaff { 1036916c50ddSTyler Retzlaff return (unsigned int)__builtin_clzll(v); 1037916c50ddSTyler Retzlaff } 1038916c50ddSTyler Retzlaff 1039916c50ddSTyler Retzlaff /** 1040916c50ddSTyler Retzlaff * Get the count of trailing 0-bits in v. 1041916c50ddSTyler Retzlaff * 1042916c50ddSTyler Retzlaff * @param v 1043916c50ddSTyler Retzlaff * The value. 1044916c50ddSTyler Retzlaff * @return 1045916c50ddSTyler Retzlaff * The count of trailing zero bits. 1046916c50ddSTyler Retzlaff */ 1047916c50ddSTyler Retzlaff static inline unsigned int 1048916c50ddSTyler Retzlaff rte_ctz32(uint32_t v) 1049916c50ddSTyler Retzlaff { 1050916c50ddSTyler Retzlaff return (unsigned int)__builtin_ctz(v); 1051916c50ddSTyler Retzlaff } 1052916c50ddSTyler Retzlaff 1053916c50ddSTyler Retzlaff /** 1054916c50ddSTyler Retzlaff * Get the count of trailing 0-bits in v. 1055916c50ddSTyler Retzlaff * 1056916c50ddSTyler Retzlaff * @param v 1057916c50ddSTyler Retzlaff * The value. 1058916c50ddSTyler Retzlaff * @return 1059916c50ddSTyler Retzlaff * The count of trailing zero bits. 1060916c50ddSTyler Retzlaff */ 1061916c50ddSTyler Retzlaff static inline unsigned int 1062916c50ddSTyler Retzlaff rte_ctz64(uint64_t v) 1063916c50ddSTyler Retzlaff { 1064916c50ddSTyler Retzlaff return (unsigned int)__builtin_ctzll(v); 1065916c50ddSTyler Retzlaff } 1066916c50ddSTyler Retzlaff 1067916c50ddSTyler Retzlaff /** 1068916c50ddSTyler Retzlaff * Get the count of 1-bits in v. 1069916c50ddSTyler Retzlaff * 1070916c50ddSTyler Retzlaff * @param v 1071916c50ddSTyler Retzlaff * The value. 1072916c50ddSTyler Retzlaff * @return 1073916c50ddSTyler Retzlaff * The count of 1-bits. 1074916c50ddSTyler Retzlaff */ 1075916c50ddSTyler Retzlaff static inline unsigned int 1076916c50ddSTyler Retzlaff rte_popcount32(uint32_t v) 1077916c50ddSTyler Retzlaff { 1078916c50ddSTyler Retzlaff return (unsigned int)__builtin_popcount(v); 1079916c50ddSTyler Retzlaff } 1080916c50ddSTyler Retzlaff 1081916c50ddSTyler Retzlaff /** 1082916c50ddSTyler Retzlaff * Get the count of 1-bits in v. 1083916c50ddSTyler Retzlaff * 1084916c50ddSTyler Retzlaff * @param v 1085916c50ddSTyler Retzlaff * The value. 1086916c50ddSTyler Retzlaff * @return 1087916c50ddSTyler Retzlaff * The count of 1-bits. 1088916c50ddSTyler Retzlaff */ 1089916c50ddSTyler Retzlaff static inline unsigned int 1090916c50ddSTyler Retzlaff rte_popcount64(uint64_t v) 1091916c50ddSTyler Retzlaff { 1092916c50ddSTyler Retzlaff return (unsigned int)__builtin_popcountll(v); 1093916c50ddSTyler Retzlaff } 1094916c50ddSTyler Retzlaff 1095*21cab84fSTyler Retzlaff /** 1096*21cab84fSTyler Retzlaff * @warning 1097*21cab84fSTyler Retzlaff * @b EXPERIMENTAL: this API may change without prior notice. 1098*21cab84fSTyler Retzlaff * 1099*21cab84fSTyler Retzlaff * Search v from least significant bit (LSB) to the most 1100*21cab84fSTyler Retzlaff * significant bit (MSB) for a set bit (1). 1101*21cab84fSTyler Retzlaff * 1102*21cab84fSTyler Retzlaff * @param v 1103*21cab84fSTyler Retzlaff * The value. 1104*21cab84fSTyler Retzlaff * @return 1105*21cab84fSTyler Retzlaff * Bit index + 1 if a set bit is found, zero otherwise. 1106*21cab84fSTyler Retzlaff */ 1107*21cab84fSTyler Retzlaff __rte_experimental 1108*21cab84fSTyler Retzlaff static inline unsigned int 1109*21cab84fSTyler Retzlaff rte_ffs32(uint32_t v) 1110*21cab84fSTyler Retzlaff { 1111*21cab84fSTyler Retzlaff return (unsigned int)__builtin_ffs(v); 1112*21cab84fSTyler Retzlaff } 1113*21cab84fSTyler Retzlaff 1114*21cab84fSTyler Retzlaff /** 1115*21cab84fSTyler Retzlaff * @warning 1116*21cab84fSTyler Retzlaff * @b EXPERIMENTAL: this API may change without prior notice. 1117*21cab84fSTyler Retzlaff * 1118*21cab84fSTyler Retzlaff * Search v from least significant bit (LSB) to the most 1119*21cab84fSTyler Retzlaff * significant bit (MSB) for a set bit (1). 1120*21cab84fSTyler Retzlaff * 1121*21cab84fSTyler Retzlaff * @param v 1122*21cab84fSTyler Retzlaff * The value. 1123*21cab84fSTyler Retzlaff * @return 1124*21cab84fSTyler Retzlaff * Bit index + 1 if a set bit is found, zero otherwise. 1125*21cab84fSTyler Retzlaff */ 1126*21cab84fSTyler Retzlaff __rte_experimental 1127*21cab84fSTyler Retzlaff static inline unsigned int 1128*21cab84fSTyler Retzlaff rte_ffs64(uint64_t v) 1129*21cab84fSTyler Retzlaff { 1130*21cab84fSTyler Retzlaff return (unsigned int)__builtin_ffsll(v); 1131*21cab84fSTyler Retzlaff } 1132*21cab84fSTyler Retzlaff 1133916c50ddSTyler Retzlaff #endif 1134916c50ddSTyler Retzlaff 11357253e3d2STyler Retzlaff /** 11367253e3d2STyler Retzlaff * Combines 32b inputs most significant set bits into the least 11377253e3d2STyler Retzlaff * significant bits to construct a value with the same MSBs as x 11387253e3d2STyler Retzlaff * but all 1's under it. 11397253e3d2STyler Retzlaff * 11407253e3d2STyler Retzlaff * @param x 11417253e3d2STyler Retzlaff * The integer whose MSBs need to be combined with its LSBs 11427253e3d2STyler Retzlaff * @return 11437253e3d2STyler Retzlaff * The combined value. 11447253e3d2STyler Retzlaff */ 11457253e3d2STyler Retzlaff static inline uint32_t 11467253e3d2STyler Retzlaff rte_combine32ms1b(uint32_t x) 11477253e3d2STyler Retzlaff { 11487253e3d2STyler Retzlaff x |= x >> 1; 11497253e3d2STyler Retzlaff x |= x >> 2; 11507253e3d2STyler Retzlaff x |= x >> 4; 11517253e3d2STyler Retzlaff x |= x >> 8; 11527253e3d2STyler Retzlaff x |= x >> 16; 11537253e3d2STyler Retzlaff 11547253e3d2STyler Retzlaff return x; 11557253e3d2STyler Retzlaff } 11567253e3d2STyler Retzlaff 11577253e3d2STyler Retzlaff /** 11587253e3d2STyler Retzlaff * Combines 64b inputs most significant set bits into the least 11597253e3d2STyler Retzlaff * significant bits to construct a value with the same MSBs as x 11607253e3d2STyler Retzlaff * but all 1's under it. 11617253e3d2STyler Retzlaff * 11627253e3d2STyler Retzlaff * @param v 11637253e3d2STyler Retzlaff * The integer whose MSBs need to be combined with its LSBs 11647253e3d2STyler Retzlaff * @return 11657253e3d2STyler Retzlaff * The combined value. 11667253e3d2STyler Retzlaff */ 11677253e3d2STyler Retzlaff static inline uint64_t 11687253e3d2STyler Retzlaff rte_combine64ms1b(uint64_t v) 11697253e3d2STyler Retzlaff { 11707253e3d2STyler Retzlaff v |= v >> 1; 11717253e3d2STyler Retzlaff v |= v >> 2; 11727253e3d2STyler Retzlaff v |= v >> 4; 11737253e3d2STyler Retzlaff v |= v >> 8; 11747253e3d2STyler Retzlaff v |= v >> 16; 11757253e3d2STyler Retzlaff v |= v >> 32; 11767253e3d2STyler Retzlaff 11777253e3d2STyler Retzlaff return v; 11787253e3d2STyler Retzlaff } 11797253e3d2STyler Retzlaff 11807253e3d2STyler Retzlaff /** 11817253e3d2STyler Retzlaff * Searches the input parameter for the least significant set bit 11827253e3d2STyler Retzlaff * (starting from zero). 11837253e3d2STyler Retzlaff * If a least significant 1 bit is found, its bit index is returned. 11847253e3d2STyler Retzlaff * If the content of the input parameter is zero, then the content of the return 11857253e3d2STyler Retzlaff * value is undefined. 11867253e3d2STyler Retzlaff * @param v 11877253e3d2STyler Retzlaff * input parameter, should not be zero. 11887253e3d2STyler Retzlaff * @return 11897253e3d2STyler Retzlaff * least significant set bit in the input parameter. 11907253e3d2STyler Retzlaff */ 11917253e3d2STyler Retzlaff static inline uint32_t 11927253e3d2STyler Retzlaff rte_bsf32(uint32_t v) 11937253e3d2STyler Retzlaff { 119418898c4dSTyler Retzlaff return (uint32_t)rte_ctz32(v); 11957253e3d2STyler Retzlaff } 11967253e3d2STyler Retzlaff 11977253e3d2STyler Retzlaff /** 11987253e3d2STyler Retzlaff * Searches the input parameter for the least significant set bit 11997253e3d2STyler Retzlaff * (starting from zero). Safe version (checks for input parameter being zero). 12007253e3d2STyler Retzlaff * 12017253e3d2STyler Retzlaff * @warning ``pos`` must be a valid pointer. It is not checked! 12027253e3d2STyler Retzlaff * 12037253e3d2STyler Retzlaff * @param v 12047253e3d2STyler Retzlaff * The input parameter. 12057253e3d2STyler Retzlaff * @param pos 12067253e3d2STyler Retzlaff * If ``v`` was not 0, this value will contain position of least significant 12077253e3d2STyler Retzlaff * bit within the input parameter. 12087253e3d2STyler Retzlaff * @return 12097253e3d2STyler Retzlaff * Returns 0 if ``v`` was 0, otherwise returns 1. 12107253e3d2STyler Retzlaff */ 12117253e3d2STyler Retzlaff static inline int 12127253e3d2STyler Retzlaff rte_bsf32_safe(uint32_t v, uint32_t *pos) 12137253e3d2STyler Retzlaff { 12147253e3d2STyler Retzlaff if (v == 0) 12157253e3d2STyler Retzlaff return 0; 12167253e3d2STyler Retzlaff 12177253e3d2STyler Retzlaff *pos = rte_bsf32(v); 12187253e3d2STyler Retzlaff return 1; 12197253e3d2STyler Retzlaff } 12207253e3d2STyler Retzlaff 12217253e3d2STyler Retzlaff /** 12227253e3d2STyler Retzlaff * Searches the input parameter for the least significant set bit 12237253e3d2STyler Retzlaff * (starting from zero). 12247253e3d2STyler Retzlaff * If a least significant 1 bit is found, its bit index is returned. 12257253e3d2STyler Retzlaff * If the content of the input parameter is zero, then the content of the return 12267253e3d2STyler Retzlaff * value is undefined. 12277253e3d2STyler Retzlaff * @param v 12287253e3d2STyler Retzlaff * input parameter, should not be zero. 12297253e3d2STyler Retzlaff * @return 12307253e3d2STyler Retzlaff * least significant set bit in the input parameter. 12317253e3d2STyler Retzlaff */ 12327253e3d2STyler Retzlaff static inline uint32_t 12337253e3d2STyler Retzlaff rte_bsf64(uint64_t v) 12347253e3d2STyler Retzlaff { 123518898c4dSTyler Retzlaff return (uint32_t)rte_ctz64(v); 12367253e3d2STyler Retzlaff } 12377253e3d2STyler Retzlaff 12387253e3d2STyler Retzlaff /** 12397253e3d2STyler Retzlaff * Searches the input parameter for the least significant set bit 12407253e3d2STyler Retzlaff * (starting from zero). Safe version (checks for input parameter being zero). 12417253e3d2STyler Retzlaff * 12427253e3d2STyler Retzlaff * @warning ``pos`` must be a valid pointer. It is not checked! 12437253e3d2STyler Retzlaff * 12447253e3d2STyler Retzlaff * @param v 12457253e3d2STyler Retzlaff * The input parameter. 12467253e3d2STyler Retzlaff * @param pos 12477253e3d2STyler Retzlaff * If ``v`` was not 0, this value will contain position of least significant 12487253e3d2STyler Retzlaff * bit within the input parameter. 12497253e3d2STyler Retzlaff * @return 12507253e3d2STyler Retzlaff * Returns 0 if ``v`` was 0, otherwise returns 1. 12517253e3d2STyler Retzlaff */ 12527253e3d2STyler Retzlaff static inline int 12537253e3d2STyler Retzlaff rte_bsf64_safe(uint64_t v, uint32_t *pos) 12547253e3d2STyler Retzlaff { 12557253e3d2STyler Retzlaff if (v == 0) 12567253e3d2STyler Retzlaff return 0; 12577253e3d2STyler Retzlaff 12587253e3d2STyler Retzlaff *pos = rte_bsf64(v); 12597253e3d2STyler Retzlaff return 1; 12607253e3d2STyler Retzlaff } 12617253e3d2STyler Retzlaff 12627253e3d2STyler Retzlaff /** 12637253e3d2STyler Retzlaff * Return the last (most-significant) bit set. 12647253e3d2STyler Retzlaff * 12657253e3d2STyler Retzlaff * @note The last (most significant) bit is at position 32. 12667253e3d2STyler Retzlaff * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32 12677253e3d2STyler Retzlaff * 12687253e3d2STyler Retzlaff * @param x 12697253e3d2STyler Retzlaff * The input parameter. 12707253e3d2STyler Retzlaff * @return 12717253e3d2STyler Retzlaff * The last (most-significant) bit set, or 0 if the input is 0. 12727253e3d2STyler Retzlaff */ 12737253e3d2STyler Retzlaff static inline uint32_t 12747253e3d2STyler Retzlaff rte_fls_u32(uint32_t x) 12757253e3d2STyler Retzlaff { 127618898c4dSTyler Retzlaff return (x == 0) ? 0 : 32 - rte_clz32(x); 12777253e3d2STyler Retzlaff } 12787253e3d2STyler Retzlaff 12797253e3d2STyler Retzlaff /** 12807253e3d2STyler Retzlaff * Return the last (most-significant) bit set. 12817253e3d2STyler Retzlaff * 12827253e3d2STyler Retzlaff * @note The last (most significant) bit is at position 64. 12837253e3d2STyler Retzlaff * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1, 12847253e3d2STyler Retzlaff * rte_fls_u64(0x8000000000000000) = 64 12857253e3d2STyler Retzlaff * 12867253e3d2STyler Retzlaff * @param x 12877253e3d2STyler Retzlaff * The input parameter. 12887253e3d2STyler Retzlaff * @return 12897253e3d2STyler Retzlaff * The last (most-significant) bit set, or 0 if the input is 0. 12907253e3d2STyler Retzlaff */ 12917253e3d2STyler Retzlaff static inline uint32_t 12927253e3d2STyler Retzlaff rte_fls_u64(uint64_t x) 12937253e3d2STyler Retzlaff { 129418898c4dSTyler Retzlaff return (x == 0) ? 0 : 64 - rte_clz64(x); 12957253e3d2STyler Retzlaff } 12967253e3d2STyler Retzlaff 12977253e3d2STyler Retzlaff /*********** Macros to work with powers of 2 ********/ 12987253e3d2STyler Retzlaff 12997253e3d2STyler Retzlaff /** 13007253e3d2STyler Retzlaff * Macro to return 1 if n is a power of 2, 0 otherwise 13017253e3d2STyler Retzlaff */ 13027253e3d2STyler Retzlaff #define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n))) 13037253e3d2STyler Retzlaff 13047253e3d2STyler Retzlaff /** 13057253e3d2STyler Retzlaff * Returns true if n is a power of 2 13067253e3d2STyler Retzlaff * @param n 13077253e3d2STyler Retzlaff * Number to check 13087253e3d2STyler Retzlaff * @return 1 if true, 0 otherwise 13097253e3d2STyler Retzlaff */ 13107253e3d2STyler Retzlaff static inline int 13117253e3d2STyler Retzlaff rte_is_power_of_2(uint32_t n) 13127253e3d2STyler Retzlaff { 13137253e3d2STyler Retzlaff return n && !(n & (n - 1)); 13147253e3d2STyler Retzlaff } 13157253e3d2STyler Retzlaff 13167253e3d2STyler Retzlaff /** 13177253e3d2STyler Retzlaff * Aligns input parameter to the next power of 2 13187253e3d2STyler Retzlaff * 13197253e3d2STyler Retzlaff * @param x 13207253e3d2STyler Retzlaff * The integer value to align 13217253e3d2STyler Retzlaff * 13227253e3d2STyler Retzlaff * @return 13237253e3d2STyler Retzlaff * Input parameter aligned to the next power of 2 13247253e3d2STyler Retzlaff */ 13257253e3d2STyler Retzlaff static inline uint32_t 13267253e3d2STyler Retzlaff rte_align32pow2(uint32_t x) 13277253e3d2STyler Retzlaff { 13287253e3d2STyler Retzlaff x--; 13297253e3d2STyler Retzlaff x = rte_combine32ms1b(x); 13307253e3d2STyler Retzlaff 13317253e3d2STyler Retzlaff return x + 1; 13327253e3d2STyler Retzlaff } 13337253e3d2STyler Retzlaff 13347253e3d2STyler Retzlaff /** 13357253e3d2STyler Retzlaff * Aligns input parameter to the previous power of 2 13367253e3d2STyler Retzlaff * 13377253e3d2STyler Retzlaff * @param x 13387253e3d2STyler Retzlaff * The integer value to align 13397253e3d2STyler Retzlaff * 13407253e3d2STyler Retzlaff * @return 13417253e3d2STyler Retzlaff * Input parameter aligned to the previous power of 2 13427253e3d2STyler Retzlaff */ 13437253e3d2STyler Retzlaff static inline uint32_t 13447253e3d2STyler Retzlaff rte_align32prevpow2(uint32_t x) 13457253e3d2STyler Retzlaff { 13467253e3d2STyler Retzlaff x = rte_combine32ms1b(x); 13477253e3d2STyler Retzlaff 13487253e3d2STyler Retzlaff return x - (x >> 1); 13497253e3d2STyler Retzlaff } 13507253e3d2STyler Retzlaff 13517253e3d2STyler Retzlaff /** 13527253e3d2STyler Retzlaff * Aligns 64b input parameter to the next power of 2 13537253e3d2STyler Retzlaff * 13547253e3d2STyler Retzlaff * @param v 13557253e3d2STyler Retzlaff * The 64b value to align 13567253e3d2STyler Retzlaff * 13577253e3d2STyler Retzlaff * @return 13587253e3d2STyler Retzlaff * Input parameter aligned to the next power of 2 13597253e3d2STyler Retzlaff */ 13607253e3d2STyler Retzlaff static inline uint64_t 13617253e3d2STyler Retzlaff rte_align64pow2(uint64_t v) 13627253e3d2STyler Retzlaff { 13637253e3d2STyler Retzlaff v--; 13647253e3d2STyler Retzlaff v = rte_combine64ms1b(v); 13657253e3d2STyler Retzlaff 13667253e3d2STyler Retzlaff return v + 1; 13677253e3d2STyler Retzlaff } 13687253e3d2STyler Retzlaff 13697253e3d2STyler Retzlaff /** 13707253e3d2STyler Retzlaff * Aligns 64b input parameter to the previous power of 2 13717253e3d2STyler Retzlaff * 13727253e3d2STyler Retzlaff * @param v 13737253e3d2STyler Retzlaff * The 64b value to align 13747253e3d2STyler Retzlaff * 13757253e3d2STyler Retzlaff * @return 13767253e3d2STyler Retzlaff * Input parameter aligned to the previous power of 2 13777253e3d2STyler Retzlaff */ 13787253e3d2STyler Retzlaff static inline uint64_t 13797253e3d2STyler Retzlaff rte_align64prevpow2(uint64_t v) 13807253e3d2STyler Retzlaff { 13817253e3d2STyler Retzlaff v = rte_combine64ms1b(v); 13827253e3d2STyler Retzlaff 13837253e3d2STyler Retzlaff return v - (v >> 1); 13847253e3d2STyler Retzlaff } 13857253e3d2STyler Retzlaff 13867253e3d2STyler Retzlaff /** 13877253e3d2STyler Retzlaff * Return the rounded-up log2 of a integer. 13887253e3d2STyler Retzlaff * 13897253e3d2STyler Retzlaff * @note Contrary to the logarithm mathematical operation, 13907253e3d2STyler Retzlaff * rte_log2_u32(0) == 0 and not -inf. 13917253e3d2STyler Retzlaff * 13927253e3d2STyler Retzlaff * @param v 13937253e3d2STyler Retzlaff * The input parameter. 13947253e3d2STyler Retzlaff * @return 13957253e3d2STyler Retzlaff * The rounded-up log2 of the input, or 0 if the input is 0. 13967253e3d2STyler Retzlaff */ 13977253e3d2STyler Retzlaff static inline uint32_t 13987253e3d2STyler Retzlaff rte_log2_u32(uint32_t v) 13997253e3d2STyler Retzlaff { 14007253e3d2STyler Retzlaff if (v == 0) 14017253e3d2STyler Retzlaff return 0; 14027253e3d2STyler Retzlaff v = rte_align32pow2(v); 14037253e3d2STyler Retzlaff return rte_bsf32(v); 14047253e3d2STyler Retzlaff } 14057253e3d2STyler Retzlaff 14067253e3d2STyler Retzlaff /** 14077253e3d2STyler Retzlaff * Return the rounded-up log2 of a 64-bit integer. 14087253e3d2STyler Retzlaff * 14097253e3d2STyler Retzlaff * @note Contrary to the logarithm mathematical operation, 14107253e3d2STyler Retzlaff * rte_log2_u64(0) == 0 and not -inf. 14117253e3d2STyler Retzlaff * 14127253e3d2STyler Retzlaff * @param v 14137253e3d2STyler Retzlaff * The input parameter. 14147253e3d2STyler Retzlaff * @return 14157253e3d2STyler Retzlaff * The rounded-up log2 of the input, or 0 if the input is 0. 14167253e3d2STyler Retzlaff */ 14177253e3d2STyler Retzlaff static inline uint32_t 14187253e3d2STyler Retzlaff rte_log2_u64(uint64_t v) 14197253e3d2STyler Retzlaff { 14207253e3d2STyler Retzlaff if (v == 0) 14217253e3d2STyler Retzlaff return 0; 14227253e3d2STyler Retzlaff v = rte_align64pow2(v); 14237253e3d2STyler Retzlaff /* we checked for v being 0 already, so no undefined behavior */ 14247253e3d2STyler Retzlaff return rte_bsf64(v); 14257253e3d2STyler Retzlaff } 14267253e3d2STyler Retzlaff 1427d7e9c02cSBrian Dooley #ifdef __cplusplus 1428d7e9c02cSBrian Dooley } 1429471de107SMattias Rönnblom 1430471de107SMattias Rönnblom /* 1431471de107SMattias Rönnblom * Since C++ doesn't support generic selection (i.e., _Generic), 1432471de107SMattias Rönnblom * function overloading is used instead. Such functions must be 1433471de107SMattias Rönnblom * defined outside 'extern "C"' to be accepted by the compiler. 1434471de107SMattias Rönnblom */ 1435471de107SMattias Rönnblom 1436471de107SMattias Rönnblom #undef rte_bit_test 1437471de107SMattias Rönnblom #undef rte_bit_set 1438471de107SMattias Rönnblom #undef rte_bit_clear 1439471de107SMattias Rönnblom #undef rte_bit_assign 1440471de107SMattias Rönnblom #undef rte_bit_flip 1441471de107SMattias Rönnblom 144235326b61SMattias Rönnblom #undef rte_bit_atomic_test 144335326b61SMattias Rönnblom #undef rte_bit_atomic_set 144435326b61SMattias Rönnblom #undef rte_bit_atomic_clear 144535326b61SMattias Rönnblom #undef rte_bit_atomic_assign 144635326b61SMattias Rönnblom #undef rte_bit_atomic_flip 144735326b61SMattias Rönnblom #undef rte_bit_atomic_test_and_set 144835326b61SMattias Rönnblom #undef rte_bit_atomic_test_and_clear 144935326b61SMattias Rönnblom #undef rte_bit_atomic_test_and_assign 145035326b61SMattias Rönnblom 1451471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_2(family, v, fun, qualifier, size, arg1_type, arg1_name) \ 1452471de107SMattias Rönnblom static inline void \ 1453471de107SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name) \ 1454471de107SMattias Rönnblom { \ 1455471de107SMattias Rönnblom __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name); \ 1456471de107SMattias Rönnblom } 1457471de107SMattias Rönnblom 1458471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, size, arg1_type, arg1_name) \ 14590883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_2(family,, fun, qualifier, size, arg1_type, arg1_name) \ 14600883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_2(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name) 1461471de107SMattias Rönnblom 1462471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_2(family, fun, qualifier, arg1_type, arg1_name) \ 1463471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, 32, arg1_type, arg1_name) \ 1464471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_2(family, fun, qualifier, 64, arg1_type, arg1_name) 1465471de107SMattias Rönnblom 1466471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_2R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name) \ 1467471de107SMattias Rönnblom static inline ret_type \ 1468471de107SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name) \ 1469471de107SMattias Rönnblom { \ 1470471de107SMattias Rönnblom return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name); \ 1471471de107SMattias Rönnblom } 1472471de107SMattias Rönnblom 1473471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name) \ 14740883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_2R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name) \ 14750883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_2R(family, v_, fun, qualifier volatile, size, ret_type, arg1_type, \ 14760883d736SMattias Rönnblom arg1_name) 1477471de107SMattias Rönnblom 1478471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_2R(family, fun, qualifier, ret_type, arg1_type, arg1_name) \ 1479471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name) \ 1480471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_2R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name) 1481471de107SMattias Rönnblom 1482471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_3(family, v, fun, qualifier, size, arg1_type, arg1_name, \ 1483471de107SMattias Rönnblom arg2_type, arg2_name) \ 1484471de107SMattias Rönnblom static inline void \ 1485471de107SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \ 1486471de107SMattias Rönnblom arg2_type arg2_name) \ 1487471de107SMattias Rönnblom { \ 1488471de107SMattias Rönnblom __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name); \ 1489471de107SMattias Rönnblom } 1490471de107SMattias Rönnblom 1491471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, size, arg1_type, arg1_name, \ 1492471de107SMattias Rönnblom arg2_type, arg2_name) \ 1493471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_V_3(family,, fun, qualifier, size, arg1_type, arg1_name, \ 14940883d736SMattias Rönnblom arg2_type, arg2_name) \ 14950883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_3(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name, \ 1496471de107SMattias Rönnblom arg2_type, arg2_name) 1497471de107SMattias Rönnblom 1498471de107SMattias Rönnblom #define __RTE_BIT_OVERLOAD_3(family, fun, qualifier, arg1_type, arg1_name, arg2_type, arg2_name) \ 1499471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, 32, arg1_type, arg1_name, \ 1500471de107SMattias Rönnblom arg2_type, arg2_name) \ 1501471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_3(family, fun, qualifier, 64, arg1_type, arg1_name, \ 1502471de107SMattias Rönnblom arg2_type, arg2_name) 1503471de107SMattias Rönnblom 150435326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_3R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name, \ 150535326b61SMattias Rönnblom arg2_type, arg2_name) \ 150635326b61SMattias Rönnblom static inline ret_type \ 150735326b61SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \ 150835326b61SMattias Rönnblom arg2_type arg2_name) \ 150935326b61SMattias Rönnblom { \ 151035326b61SMattias Rönnblom return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name); \ 151135326b61SMattias Rönnblom } 151235326b61SMattias Rönnblom 151335326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name, \ 151435326b61SMattias Rönnblom arg2_type, arg2_name) \ 151535326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_V_3R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name, \ 15160883d736SMattias Rönnblom arg2_type, arg2_name) \ 15170883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_3R(family, v_, fun, qualifier volatile, size, ret_type, \ 15180883d736SMattias Rönnblom arg1_type, arg1_name, arg2_type, arg2_name) 151935326b61SMattias Rönnblom 152035326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_3R(family, fun, qualifier, ret_type, arg1_type, arg1_name, \ 152135326b61SMattias Rönnblom arg2_type, arg2_name) \ 152235326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name, \ 152335326b61SMattias Rönnblom arg2_type, arg2_name) \ 152435326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_3R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name, \ 152535326b61SMattias Rönnblom arg2_type, arg2_name) 152635326b61SMattias Rönnblom 152735326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_4(family, v, fun, qualifier, size, arg1_type, arg1_name, \ 152835326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 152935326b61SMattias Rönnblom static inline void \ 153035326b61SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \ 153135326b61SMattias Rönnblom arg2_type arg2_name, arg3_type arg3_name) \ 153235326b61SMattias Rönnblom { \ 153335326b61SMattias Rönnblom __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name, arg3_name); \ 153435326b61SMattias Rönnblom } 153535326b61SMattias Rönnblom 153635326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, size, arg1_type, arg1_name, \ 153735326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 153835326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_V_4(family,, fun, qualifier, size, arg1_type, arg1_name, \ 15390883d736SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 15400883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_4(family, v_, fun, qualifier volatile, size, arg1_type, arg1_name, \ 154135326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) 154235326b61SMattias Rönnblom 154335326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_4(family, fun, qualifier, arg1_type, arg1_name, arg2_type, arg2_name, \ 154435326b61SMattias Rönnblom arg3_type, arg3_name) \ 154535326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, 32, arg1_type, arg1_name, \ 154635326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 154735326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_4(family, fun, qualifier, 64, arg1_type, arg1_name, \ 154835326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) 154935326b61SMattias Rönnblom 155035326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_V_4R(family, v, fun, qualifier, size, ret_type, arg1_type, arg1_name, \ 155135326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 155235326b61SMattias Rönnblom static inline ret_type \ 155335326b61SMattias Rönnblom rte_bit_ ## family ## fun(qualifier uint ## size ## _t *addr, arg1_type arg1_name, \ 155435326b61SMattias Rönnblom arg2_type arg2_name, arg3_type arg3_name) \ 155535326b61SMattias Rönnblom { \ 155635326b61SMattias Rönnblom return __rte_bit_ ## family ## v ## fun ## size(addr, arg1_name, arg2_name, \ 155735326b61SMattias Rönnblom arg3_name); \ 155835326b61SMattias Rönnblom } 155935326b61SMattias Rönnblom 156035326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, size, ret_type, arg1_type, arg1_name, \ 156135326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 156235326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_V_4R(family,, fun, qualifier, size, ret_type, arg1_type, arg1_name, \ 15630883d736SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 15640883d736SMattias Rönnblom __RTE_BIT_OVERLOAD_V_4R(family, v_, fun, qualifier volatile, size, ret_type, \ 15650883d736SMattias Rönnblom arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) 156635326b61SMattias Rönnblom 156735326b61SMattias Rönnblom #define __RTE_BIT_OVERLOAD_4R(family, fun, qualifier, ret_type, arg1_type, arg1_name, \ 156835326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 156935326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, 32, ret_type, arg1_type, arg1_name, \ 157035326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) \ 157135326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_SZ_4R(family, fun, qualifier, 64, ret_type, arg1_type, arg1_name, \ 157235326b61SMattias Rönnblom arg2_type, arg2_name, arg3_type, arg3_name) 157335326b61SMattias Rönnblom 15748b65ddc0SDavid Marchand #ifdef ALLOW_EXPERIMENTAL_API 1575471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2R(, test, const, bool, unsigned int, nr) 1576471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2(, set,, unsigned int, nr) 1577471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2(, clear,, unsigned int, nr) 1578471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_3(, assign,, unsigned int, nr, bool, value) 1579471de107SMattias Rönnblom __RTE_BIT_OVERLOAD_2(, flip,, unsigned int, nr) 1580471de107SMattias Rönnblom 158135326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3R(atomic_, test, const, bool, unsigned int, nr, int, memory_order) 158235326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3(atomic_, set,, unsigned int, nr, int, memory_order) 158335326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3(atomic_, clear,, unsigned int, nr, int, memory_order) 158435326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_4(atomic_, assign,, unsigned int, nr, bool, value, int, memory_order) 158535326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3(atomic_, flip,, unsigned int, nr, int, memory_order) 158635326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3R(atomic_, test_and_set,, bool, unsigned int, nr, int, memory_order) 158735326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_3R(atomic_, test_and_clear,, bool, unsigned int, nr, int, memory_order) 158835326b61SMattias Rönnblom __RTE_BIT_OVERLOAD_4R(atomic_, test_and_assign,, bool, unsigned int, nr, bool, value, 158935326b61SMattias Rönnblom int, memory_order) 15908b65ddc0SDavid Marchand #endif 159135326b61SMattias Rönnblom 1592d7e9c02cSBrian Dooley #endif 1593d7e9c02cSBrian Dooley 159499a2dd95SBruce Richardson #endif /* _RTE_BITOPS_H_ */ 1595