From: Mark Rutland mark.rutland@arm.com
mainline inclusion from mainline-v5.17-rc1 commit 7ad639840acf2800b5f387c495795f995a67a329 category: performance bugzilla: https://gitee.com/openeuler/kernel/issues/IA5WFA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
In <linux/thread_info.h> there are helpers to manipulate individual thread flags, but where code wants to check several flags at once, it must open code reading current_thread_info()->flags and operating on a snapshot.
As some flags can be set remotely it's necessary to use READ_ONCE() to get a consistent snapshot even when IRQs are disabled, but some code forgets to do this. Generally this is unlike to cause a problem in practice, but it is somewhat unsound, and KCSAN will legitimately warn that there is a data race.
To make it easier to do the right thing, and to highlight that concurrent modification is possible, add new helpers to snapshot the flags, which should be used in preference to plain reads. Subsequent patches will move existing code to use the new helpers.
Signed-off-by: Mark Rutland mark.rutland@arm.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Thomas Gleixner tglx@linutronix.de Acked-by: Marco Elver elver@google.com Acked-by: Paul E. McKenney paulmck@kernel.org Cc: Boqun Feng boqun.feng@gmail.com Cc: Dmitry Vyukov dvyukov@google.com Cc: Peter Zijlstra peterz@infradead.org Cc: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20211129130653.2037928-2-mark.rutland@arm.com
Conflict: include/linux/thread_info.h
Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/thread_info.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 19f76d87f20f..af3ca6429d77 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -36,6 +36,21 @@ static inline long set_restart_fn(struct restart_block *restart,
#define THREADINFO_GFP (GFP_KERNEL_ACCOUNT | __GFP_ZERO)
+/* + * This may be used in noinstr code, and needs to be __always_inline to prevent + * inadvertent instrumentation. + */ +static __always_inline unsigned long read_ti_thread_flags(struct thread_info *ti) +{ + return READ_ONCE(ti->flags); +} + +#define read_thread_flags() \ + read_ti_thread_flags(current_thread_info()) + +#define read_task_thread_flags(t) \ + read_ti_thread_flags(task_thread_info(t)) + #define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
#ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES