On Tue, Dec 17, 2019 at 10:32:35AM -0800, Linus Torvalds wrote:
> On Tue, Dec 17, 2019 at 10:04 AM Linus Torvalds
> <torva...@linux-foundation.org> wrote:
> >
> > Let me think about it.
> 
> How about we just get rid of the union entirely, and just use
> 'unsigned long' or 'unsigned long long' depending on the size.
> 
> Something like the attached patch - it still requires that it be an
> arithmetic type, but now because of the final cast.
> 
> But it might still be a cast to a volatile type, of course. Then the
> result will be volatile, but at least now READ_ONCE() won't be taking
> the address of a volatile variable on the stack - does that at least
> fix some of the horrible code generation. Hmm?

Sounds like it according to mpe, but I'll confirm too for arm64.

> This is untested, because I obviously still have the cases of
> structures (page table entries) being accessed once..
> 
>               Linus

>  include/linux/compiler.h | 33 +++++++++++++++++----------------
>  1 file changed, 17 insertions(+), 16 deletions(-)
> 
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 5e88e7e33abe..8b4282194f16 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -179,18 +179,18 @@ void ftrace_likely_update(struct ftrace_likely_data *f, 
> int val,
>  
>  #include <uapi/linux/types.h>
>  
> -#define __READ_ONCE_SIZE                                             \
> -({                                                                   \
> -     switch (size) {                                                 \
> -     case 1: *(__u8 *)res = *(volatile __u8 *)p; break;              \
> -     case 2: *(__u16 *)res = *(volatile __u16 *)p; break;            \
> -     case 4: *(__u32 *)res = *(volatile __u32 *)p; break;            \
> -     case 8: *(__u64 *)res = *(volatile __u64 *)p; break;            \
> -     default:                                                        \
> -             barrier();                                              \
> -             __builtin_memcpy((void *)res, (const void *)p, size);   \
> -             barrier();                                              \
> -     }                                                               \
> +/* "unsigned long" or "unsigned long long" - make it fit in a register if 
> possible */
> +#define __READ_ONCE_TYPE(size) \
> +     __typeof__(__builtin_choose_expr(size > sizeof(0UL), 0ULL, 0UL))

Ha, I wondered when '__builtin_choose_expr()' would make an appearance in
this thread! Nice trick. I'll try integrating this with what I have and see
what I run into next.

Back down the rabbit hole...

Will

Reply via email to