Re: [RFC PATCH 6/8] READ_ONCE: Drop pointer qualifiers when reading from scalar types

From: Linus Torvalds
Date: Fri Jan 10 2020 - 13:54:51 EST


On Fri, Jan 10, 2020 at 8:56 AM Will Deacon <will@xxxxxxxxxx> wrote:
>
> +/* Declare an unqualified scalar type. Leaves non-scalar types unchanged. */
> +#define __unqual_scalar_typeof(x) typeof( \

Ugh. My eyes. That's horrendous.

I can't see any better alternatives, but it does make me go "Eww".

Well, I do see one possible alternative: just re-write the bitop
implementations in terms of "atomic_long_t", and just avoid the issue
entirely.

IOW, do something like the attached (but fleshed out and tested - this
patch has not seen a compiler, much less any thought at all).

Linus
include/asm-generic/bitops/lock.h | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
index 3ae021368f48..071d8bfd86e5 100644
--- a/include/asm-generic/bitops/lock.h
+++ b/include/asm-generic/bitops/lock.h
@@ -6,6 +6,12 @@
#include <linux/compiler.h>
#include <asm/barrier.h>

+/* Drop the volatile, we will be doing READ_ONCE by hand */
+static inline atomic_long_t *atomic_long_bit_word(unsigned int nr, volatile unsigned long *p)
+{
+ return BIT_WORD(nr) + (atomic_long_t *)p;
+}
+
/**
* test_and_set_bit_lock - Set a bit and return its old value, for lock
* @nr: Bit to set
@@ -20,12 +26,12 @@ static inline int test_and_set_bit_lock(unsigned int nr,
{
long old;
unsigned long mask = BIT_MASK(nr);
+ atomic_long_t *loc = atomic_long_bit_word(nr, p);

- p += BIT_WORD(nr);
- if (READ_ONCE(*p) & mask)
+ if (atomic_read(loc) & mask)
return 1;

- old = atomic_long_fetch_or_acquire(mask, (atomic_long_t *)p);
+ old = atomic_long_fetch_or_acquire(mask, loc);
return !!(old & mask);
}