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

task_work: Introduce task_work_pending

Wrap the test of task->task_works in a helper function to make
it clear what is being tested.

All of the other readers of task->task_work use READ_ONCE and this is
even necessary on current as other processes can update
task->task_work. So for consistency I have added READ_ONCE into
task_work_pending.

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

+13 -8
+3 -3
fs/io_uring.c
··· 2590 2590 2591 2591 static inline bool io_run_task_work(void) 2592 2592 { 2593 - if (test_thread_flag(TIF_NOTIFY_SIGNAL) || current->task_works) { 2593 + if (test_thread_flag(TIF_NOTIFY_SIGNAL) || task_work_pending(current)) { 2594 2594 __set_current_state(TASK_RUNNING); 2595 2595 tracehook_notify_signal(); 2596 2596 return true; ··· 7602 7602 } 7603 7603 7604 7604 prepare_to_wait(&sqd->wait, &wait, TASK_INTERRUPTIBLE); 7605 - if (!io_sqd_events_pending(sqd) && !current->task_works) { 7605 + if (!io_sqd_events_pending(sqd) && !task_work_pending(current)) { 7606 7606 bool needs_sched = true; 7607 7607 7608 7608 list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { ··· 10321 10321 10322 10322 hlist_for_each_entry(req, list, hash_node) 10323 10323 seq_printf(m, " op=%d, task_works=%d\n", req->opcode, 10324 - req->task->task_works != NULL); 10324 + task_work_pending(req->task)); 10325 10325 } 10326 10326 10327 10327 seq_puts(m, "CqOverflowList:\n");
+5
include/linux/task_work.h
··· 19 19 TWA_SIGNAL, 20 20 }; 21 21 22 + static inline bool task_work_pending(struct task_struct *task) 23 + { 24 + return READ_ONCE(task->task_works); 25 + } 26 + 22 27 int task_work_add(struct task_struct *task, struct callback_head *twork, 23 28 enum task_work_notify_mode mode); 24 29
+2 -2
include/linux/tracehook.h
··· 90 90 * hlist_add_head(task->task_works); 91 91 */ 92 92 smp_mb__after_atomic(); 93 - if (unlikely(current->task_works)) 93 + if (unlikely(task_work_pending(current))) 94 94 task_work_run(); 95 95 96 96 #ifdef CONFIG_KEYS_REQUEST_CACHE ··· 115 115 { 116 116 clear_thread_flag(TIF_NOTIFY_SIGNAL); 117 117 smp_mb__after_atomic(); 118 - if (current->task_works) 118 + if (task_work_pending(current)) 119 119 task_work_run(); 120 120 } 121 121
+2 -2
kernel/signal.c
··· 2344 2344 void ptrace_notify(int exit_code) 2345 2345 { 2346 2346 BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); 2347 - if (unlikely(current->task_works)) 2347 + if (unlikely(task_work_pending(current))) 2348 2348 task_work_run(); 2349 2349 2350 2350 spin_lock_irq(&current->sighand->siglock); ··· 2626 2626 struct signal_struct *signal = current->signal; 2627 2627 int signr; 2628 2628 2629 - if (unlikely(current->task_works)) 2629 + if (unlikely(task_work_pending(current))) 2630 2630 task_work_run(); 2631 2631 2632 2632 /*
+1 -1
kernel/task_work.c
··· 78 78 struct callback_head *work; 79 79 unsigned long flags; 80 80 81 - if (likely(!task->task_works)) 81 + if (likely(!task_work_pending(task))) 82 82 return NULL; 83 83 /* 84 84 * If cmpxchg() fails we continue without updating pprev.