If JOBCTL_TASK_WORK is already set on the targeted task, then we need
not go through {lock,unlock}_task_sighand() to set it again and queue
a signal wakeup. This is safe as we're checking it _after adding the
new task_work with cmpxchg().

Signed-off-by: Jens Axboe <ax...@kernel.dk>

---

Tested this with an intensive task_work based io_uring workload, and
the benefits are quite large.

diff --git a/kernel/task_work.c b/kernel/task_work.c
index 5c0848ca1287..cbf8cab6e864 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -42,7 +42,8 @@ task_work_add(struct task_struct *task, struct callback_head 
*work, int notify)
                set_notify_resume(task);
                break;
        case TWA_SIGNAL:
-               if (lock_task_sighand(task, &flags)) {
+               if (!(READ_ONCE(task->jobctl) & JOBCTL_TASK_WORK) &&
+                   lock_task_sighand(task, &flags)) {
                        task->jobctl |= JOBCTL_TASK_WORK;
                        signal_wake_up(task, 0);
                        unlock_task_sighand(task, &flags);
-- 
Jens Axboe

Reply via email to