[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v10 02/14] xen: introduce generic non-atomic test_*bit()
On 23/05/2024 15:11, Oleksii K. wrote: On Thu, 2024-05-23 at 14:00 +0100, Julien Grall wrote:Hi Oleksii,Hi Julien,On 17/05/2024 14:54, Oleksii Kurochko wrote:diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c index df2cebedde..4bc8ed9be5 100644 --- a/xen/arch/arm/arm64/livepatch.c +++ b/xen/arch/arm/arm64/livepatch.c @@ -10,7 +10,6 @@ #include <xen/mm.h> #include <xen/vmap.h>-#include <asm/bitops.h>It is a bit unclear how this change is related to the patch. Can you explain in the commit message?Probably it doesn't need anymore. I will double check and if this change is not needed, I will just drop it in the next patch version.#include <asm/byteorder.h> #include <asm/insn.h> #include <asm/livepatch.h> diff --git a/xen/arch/arm/include/asm/bitops.h b/xen/arch/arm/include/asm/bitops.h index 5104334e48..8e16335e76 100644 --- a/xen/arch/arm/include/asm/bitops.h +++ b/xen/arch/arm/include/asm/bitops.h @@ -22,9 +22,6 @@ #define __set_bit(n,p) set_bit(n,p) #define __clear_bit(n,p) clear_bit(n,p)-#define BITOP_BITS_PER_WORD 32-#define BITOP_MASK(nr) (1UL << ((nr) % BITOP_BITS_PER_WORD)) -#define BITOP_WORD(nr) ((nr) / BITOP_BITS_PER_WORD) #define BITS_PER_BYTE 8OOI, any reason BITS_PER_BYTE has not been moved as well? I don't expect the value to change across arch.I can move it to generic one header too in the next patch version.[...]diff --git a/xen/include/xen/bitops.h b/xen/include/xen/bitops.h index f14ad0d33a..6eeeff0117 100644 --- a/xen/include/xen/bitops.h +++ b/xen/include/xen/bitops.h @@ -65,10 +65,141 @@ static inline int generic_flsl(unsigned long x) * scope */+#define BITOP_BITS_PER_WORD 32+typedef uint32_t bitop_uint_t; + +#define BITOP_MASK(nr) ((bitop_uint_t)1 << ((nr) % BITOP_BITS_PER_WORD)) + +#define BITOP_WORD(nr) ((nr) / BITOP_BITS_PER_WORD) + +extern void __bitop_bad_size(void); + +#define bitop_bad_size(addr) (sizeof(*(addr)) < sizeof(bitop_uint_t)) + /* --------------------- Please tidy above here ----------------- ---- */#include <asm/bitops.h> +/**+ * generic__test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */Sorry for only mentioning this on v10. I think this comment should be duplicated (or moved to) on top of test_bit() because this is what everyone will use. This will avoid the developper to follow the function calls and only notice the x86 version which says "This function is atomic and may not be reordered." and would be wrong for all the other arch.It makes sense to add this comment on top of test_bit(), but I am curious if it is needed to mention that for x86 arch_test_bit() "is atomic and may not be reordered": I would say no because any developper modifying common code can't relying it. * This operation is non-atomic and can be reordered. ( Exception: for * x86 arch_test_bit() is atomic and may not be reordered ) * If two examples of this operation race, one can appear to succeed * but actually fail. You must protect multiple accesses with a lock. */+static always_inline bool +generic__test_and_set_bit(int nr, volatile void *addr) +{ + bitop_uint_t mask = BITOP_MASK(nr); + volatile bitop_uint_t *p = (volatile bitop_uint_t *)addr + BITOP_WORD(nr); + bitop_uint_t old = *p; + + *p = old | mask; + return (old & mask); +} + +/** + * generic__test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to clear + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */Same applies here and ...+static always_inline bool +generic__test_and_clear_bit(int nr, volatile void *addr) +{ + bitop_uint_t mask = BITOP_MASK(nr); + volatile bitop_uint_t *p = (volatile bitop_uint_t *)addr + BITOP_WORD(nr); + bitop_uint_t old = *p; + + *p = old & ~mask; + return (old & mask); +} + +/* WARNING: non atomic and it can be reordered! */... here.+static always_inline bool +generic__test_and_change_bit(int nr, volatile void *addr) +{ + bitop_uint_t mask = BITOP_MASK(nr); + volatile bitop_uint_t *p = (volatile bitop_uint_t *)addr + BITOP_WORD(nr); + bitop_uint_t old = *p; + + *p = old ^ mask; + return (old & mask); +} +/** + * generic_test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +static always_inline bool generic_test_bit(int nr, const volatile void *addr) +{ + bitop_uint_t mask = BITOP_MASK(nr); + const volatile bitop_uint_t *p = + (const volatile bitop_uint_t *)addr + BITOP_WORD(nr); + + return (*p & mask); +} + +static always_inline bool +__test_and_set_bit(int nr, volatile void *addr) +{ +#ifndef arch__test_and_set_bit +#define arch__test_and_set_bit generic__test_and_set_bit +#endif + + return arch__test_and_set_bit(nr, addr); +}NIT: It is a bit too late to change this one. But I have to admit, I don't understand the purpose of the static inline when you could have simply call...+#define __test_and_set_bit(nr, addr) ({ \ + if ( bitop_bad_size(addr) ) __bitop_bad_size(); \ + __test_and_set_bit(nr, addr); \... __arch__test_and_set_bit here.I just wanted to be in sync with other non-atomic test*_bit() operations and Andrew's patch series ( xen/bitops: Reduce the mess, starting with ffs() ). I looked at Andrew series and I can't seem to find an example where he uses both the macro + static inline. He seems only use a static inline. Do you have any pointer?But by any chance are you referring to the pattern on x86? If so, I would really like to understand what's the benefits of introducing a a one-liner static inline which is "shadowed" by a macro... Cheers, -- Julien Grall
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |