i see worse inlining decisions from gcc with this. maybe you see an improvement that would justify it? [ref: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99998] diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index 4819d5e5a335..4cbc5bd5bcdd 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -60,6 +60,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index, #define __smp_mb() asm volatile("lock; addl $0,-4(%%rsp)" ::: "memory", "cc") #endif #define __smp_rmb() dma_rmb() +#define smp_rmb_cond(x) barrier() #define __smp_wmb() barrier() #define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0) diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h index 640f09479bdf..cc0c864f90dc 100644 --- a/include/asm-generic/barrier.h +++ b/include/asm-generic/barrier.h @@ -89,6 +89,10 @@ #endif /* CONFIG_SMP */ +#ifndef smp_rmb_cond +#define smp_rmb_cond(x) do { if (x) smp_rmb(); } while (0) +#endif + #ifndef __smp_store_mb #define __smp_store_mb(var, value) do { WRITE_ONCE(var, value); __smp_mb(); } while (0) #endif diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 04a34c08e0a6..c45d491e9245 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -522,8 +522,7 @@ static inline int PageUptodate(struct page *page) * * See SetPageUptodate() for the other side of the story. */ - if (ret) - smp_rmb(); + smp_rmb_cond(ret); return ret; } diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 7a1414622051..260ef2474ff2 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -89,8 +89,7 @@ static __printf(2, 0) int printk_safe_log_store(struct printk_safe_seq_buf *s, * Make sure that all old data have been read before the buffer * was reset. This is not needed when we just append data. */ - if (!len) - smp_rmb(); + smp_rmb_cond(!len); va_copy(ap, args); add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, ap);