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.
Unified · Split
| @@ -515,7 +515,9 @@ static bool io_flush_signals(void) · 514 unmodified lines | |||
| 515 | { | 515 | { |
| 516 | if (unlikely(test_thread_flag(TIF_NOTIFY_SIGNAL))) { | 516 | if (unlikely(test_thread_flag(TIF_NOTIFY_SIGNAL))) { |
| 517 | __set_current_state(TASK_RUNNING); | 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 | return true; | 521 | return true; |
| 520 | } | 522 | } |
| 521 | return false; | 523 | return false; |
| @@ -2592,7 +2592,9 @@ static inline bool io_run_task_work(void) · 2591 unmodified lines | |||
| 2592 | { | 2592 | { |
| 2593 | if (test_thread_flag(TIF_NOTIFY_SIGNAL) || task_work_pending(current)) { | 2593 | if (test_thread_flag(TIF_NOTIFY_SIGNAL) || task_work_pending(current)) { |
| 2594 | __set_current_state(TASK_RUNNING); | 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 | return true; | 2598 | return true; |
| 2597 | } | 2599 | } |
| 2598 | 2600 | ||
| @@ -113,19 +113,8 @@ static inline void clear_notify_signal(void) · 112 unmodified lines | |||
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | /* | 115 | /* |
| 116 | * called by exit_to_user_mode_loop() if ti_work & _TIF_NOTIFY_SIGNAL. This | 116 | * Called to break out of interruptible wait loops, and enter the |
| 117 | * is currently used by TWA_SIGNAL based task_work, which requires breaking | 117 | * exit_to_user_mode_loop(). |
| 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() | ||
| 129 | */ | 118 | */ |
| 130 | static inline void set_notify_signal(struct task_struct *task) | 119 | static inline void set_notify_signal(struct task_struct *task) |
| 131 | { | 120 | { |
| @@ -8,8 +8,11 @@ static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work) · 7 unmodified lines | |||
| 8 | do { | 8 | do { |
| 9 | int ret; | 9 | int ret; |
| 10 | 10 | ||
| 11 | if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) | 11 | if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) { |
| 12 | tracehook_notify_signal(); | 12 | clear_notify_signal(); |
| 13 | if (task_work_pending(current)) | ||
| 14 | task_work_run(); | ||
| 15 | } | ||
| 13 | 16 | ||
| 14 | if (ti_work & _TIF_SIGPENDING) { | 17 | if (ti_work & _TIF_SIGPENDING) { |
| 15 | kvm_handle_signal_exit(vcpu); | 18 | kvm_handle_signal_exit(vcpu); |