Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

task_work: Decouple TIF_NOTIFY_SIGNAL and task_work

There are a small handful of reasons besides pending signals that the
kernel might want to break out of interruptible sleeps. The flag
TIF_NOTIFY_SIGNAL and the helpers that set and clear TIF_NOTIFY_SIGNAL
provide that the infrastructure for breaking out of interruptible
sleeps and entering the return to user space slow path for those
cases.

Expand tracehook_notify_signal inline in it's callers and remove it,
which makes clear that TIF_NOTIFY_SIGNAL and task_work are separate
concepts.

Update the comment on set_notify_signal to more accurately describe
it's purpose.

Reviewed-by: Kees Cook <keescook@chromium.org>
Link: https://lkml.kernel.org/r/20220309162454.123006-9-ebiederm@xmission.com
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

+13 -17
+3 -1
fs/io-wq.c
··· 515 515 { 516 516 if (unlikely(test_thread_flag(TIF_NOTIFY_SIGNAL))) { 517 517 __set_current_state(TASK_RUNNING); 518 - tracehook_notify_signal(); 518 + clear_notify_signal(); 519 + if (task_work_pending(current)) 520 + task_work_run(); 519 521 return true; 520 522 } 521 523 return false;
+3 -1
fs/io_uring.c
··· 2592 2592 { 2593 2593 if (test_thread_flag(TIF_NOTIFY_SIGNAL) || task_work_pending(current)) { 2594 2594 __set_current_state(TASK_RUNNING); 2595 - tracehook_notify_signal(); 2595 + clear_notify_signal(); 2596 + if (task_work_pending(current)) 2597 + task_work_run(); 2596 2598 return true; 2597 2599 } 2598 2600
+2 -13
include/linux/tracehook.h
··· 113 113 } 114 114 115 115 /* 116 - * called by exit_to_user_mode_loop() if ti_work & _TIF_NOTIFY_SIGNAL. This 117 - * is currently used by TWA_SIGNAL based task_work, which requires breaking 118 - * wait loops to ensure that task_work is noticed and run. 119 - */ 120 - static inline void tracehook_notify_signal(void) 121 - { 122 - clear_notify_signal(); 123 - if (task_work_pending(current)) 124 - task_work_run(); 125 - } 126 - 127 - /* 128 - * Called when we have work to process from exit_to_user_mode_loop() 116 + * Called to break out of interruptible wait loops, and enter the 117 + * exit_to_user_mode_loop(). 129 118 */ 130 119 static inline void set_notify_signal(struct task_struct *task) 131 120 {
+5 -2
kernel/entry/kvm.c
··· 8 8 do { 9 9 int ret; 10 10 11 - if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) 12 - tracehook_notify_signal(); 11 + if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) { 12 + clear_notify_signal(); 13 + if (task_work_pending(current)) 14 + task_work_run(); 15 + } 13 16 14 17 if (ti_work & _TIF_SIGPENDING) { 15 18 kvm_handle_signal_exit(vcpu);