]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
um: Re-evaluate thread flags repeatedly
authorThomas Weißschuh <thomas.weissschuh@linutronix.de>
Fri, 4 Jul 2025 12:34:47 +0000 (14:34 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 11 Jul 2025 06:49:02 +0000 (08:49 +0200)
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>
arch/um/include/asm/thread_info.h
arch/um/kernel/process.c

index b8c021f97bd17515e4f9082206addfce05b9321e..545d298c1b2345a4324ce12aaf803b2e14cd0d0a 100644 (file)
@@ -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
index 0cd6fad3d908d43e84ebc821676e05377ec641e9..1be644de9e41ecdb94d379760ee8790c1d0657c6 100644 (file)
@@ -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 = &current->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)