diff options
author | Thomas Weißschuh <thomas.weissschuh@linutronix.de> | 2025-07-04 14:34:47 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2025-07-11 08:49:02 +0200 |
commit | b9e2f2246eb2b5617d53af7b5e4e1b8c916f26a8 (patch) | |
tree | fd585d2c660645ff47c7864790b58b3d13739f84 | |
parent | ac1ad16f10523c2c60aef0abeb8a850ea6d06ced (diff) |
um: Re-evaluate thread flags repeatedly
The thread flags may change during their processing.
For example a task_work can queue a new signal to be sent.
This signal should be delivered before returning to usespace again.
Evaluate the flags repeatedly similar to other architectures.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Nam Cao <namcao@linutronix.de>
Link: https://patch.msgid.link/20250704-uml-thread_flags-v1-1-0e293fd8d627@linutronix.de
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | arch/um/include/asm/thread_info.h | 4 | ||||
-rw-r--r-- | arch/um/kernel/process.c | 20 |
2 files changed, 16 insertions, 8 deletions
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index b8c021f97bd1..545d298c1b23 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -52,7 +52,11 @@ struct thread_info { #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) #define _TIF_MEMDIE (1 << TIF_MEMDIE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) +#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \ + _TIF_NOTIFY_RESUME) + #endif diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 0cd6fad3d908..1be644de9e41 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -82,14 +82,18 @@ struct task_struct *__switch_to(struct task_struct *from, struct task_struct *to void interrupt_end(void) { struct pt_regs *regs = ¤t->thread.regs; - - if (need_resched()) - schedule(); - if (test_thread_flag(TIF_SIGPENDING) || - test_thread_flag(TIF_NOTIFY_SIGNAL)) - do_signal(regs); - if (test_thread_flag(TIF_NOTIFY_RESUME)) - resume_user_mode_work(regs); + unsigned long thread_flags; + + thread_flags = read_thread_flags(); + while (thread_flags & _TIF_WORK_MASK) { + if (thread_flags & _TIF_NEED_RESCHED) + schedule(); + if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) + do_signal(regs); + if (thread_flags & _TIF_NOTIFY_RESUME) + resume_user_mode_work(regs); + thread_flags = read_thread_flags(); + } } int get_current_pid(void) |