| From dd36929720f40f17685e841ae0d4c581c165ea60 Mon Sep 17 00:00:00 2001 |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| Date: Fri, 20 Feb 2015 15:46:31 -0800 |
| Subject: kernel: make READ_ONCE() valid on const arguments |
| |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| commit dd36929720f40f17685e841ae0d4c581c165ea60 upstream. |
| |
| The use of READ_ONCE() causes lots of warnings witht he pending paravirt |
| spinlock fixes, because those ends up having passing a member to a |
| 'const' structure to READ_ONCE(). |
| |
| There should certainly be nothing wrong with using READ_ONCE() with a |
| const source, but the helper function __read_once_size() would cause |
| warnings because it would drop the 'const' qualifier, but also because |
| the destination would be marked 'const' too due to the use of 'typeof'. |
| |
| Use a union of types in READ_ONCE() to avoid this issue. |
| |
| Also make sure to use parenthesis around the macro arguments to avoid |
| possible operator precedence issues. |
| |
| Tested-by: Ingo Molnar <mingo@kernel.org> |
| Cc: Christian Borntraeger <borntraeger@de.ibm.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| include/linux/compiler.h | 6 +++--- |
| 1 file changed, 3 insertions(+), 3 deletions(-) |
| |
| --- a/include/linux/compiler.h |
| +++ b/include/linux/compiler.h |
| @@ -198,7 +198,7 @@ static __always_inline void data_access_ |
| { |
| } |
| |
| -static __always_inline void __read_once_size(volatile void *p, void *res, int size) |
| +static __always_inline void __read_once_size(const volatile void *p, void *res, int size) |
| { |
| switch (size) { |
| case 1: *(__u8 *)res = *(volatile __u8 *)p; break; |
| @@ -255,10 +255,10 @@ static __always_inline void __write_once |
| */ |
| |
| #define READ_ONCE(x) \ |
| - ({ typeof(x) __val; __read_once_size(&x, &__val, sizeof(__val)); __val; }) |
| + ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) |
| |
| #define WRITE_ONCE(x, val) \ |
| - ({ typeof(x) __val; __val = val; __write_once_size(&x, &__val, sizeof(__val)); __val; }) |
| + ({ typeof(x) __val = (val); __write_once_size(&(x), &__val, sizeof(__val)); __val; }) |
| |
| #endif /* __KERNEL__ */ |
| |