Skip to content

Commit 61e9649

Browse files
oleg-nesterovtorvalds
authored andcommitted
task_work: use READ_ONCE/lockless_dereference, avoid pi_lock if !task_works
Change task_work_cancel() to use lockless_dereference(), this is what the code really wants but we didn't have this helper when it was written. Also add the fast-path task->task_works == NULL check, in the likely case this task has no pending works and we can avoid spin_lock(task->pi_lock). While at it, change other users of ACCESS_ONCE() to use READ_ONCE(). Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Oleg Nesterov <[email protected]> Cc: Andrea Parri <[email protected]> Cc: Peter Zijlstra <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 949bed2 commit 61e9649

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

kernel/task_work.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ task_work_add(struct task_struct *task, struct callback_head *work, bool notify)
2929
struct callback_head *head;
3030

3131
do {
32-
head = ACCESS_ONCE(task->task_works);
32+
head = READ_ONCE(task->task_works);
3333
if (unlikely(head == &work_exited))
3434
return -ESRCH;
3535
work->next = head;
@@ -57,15 +57,17 @@ task_work_cancel(struct task_struct *task, task_work_func_t func)
5757
struct callback_head **pprev = &task->task_works;
5858
struct callback_head *work;
5959
unsigned long flags;
60+
61+
if (likely(!task->task_works))
62+
return NULL;
6063
/*
6164
* If cmpxchg() fails we continue without updating pprev.
6265
* Either we raced with task_work_add() which added the
6366
* new entry before this work, we will find it again. Or
6467
* we raced with task_work_run(), *pprev == NULL/exited.
6568
*/
6669
raw_spin_lock_irqsave(&task->pi_lock, flags);
67-
while ((work = ACCESS_ONCE(*pprev))) {
68-
smp_read_barrier_depends();
70+
while ((work = lockless_dereference(*pprev))) {
6971
if (work->func != func)
7072
pprev = &work->next;
7173
else if (cmpxchg(pprev, work, work->next) == work)
@@ -95,7 +97,7 @@ void task_work_run(void)
9597
* work_exited unless the list is empty.
9698
*/
9799
do {
98-
work = ACCESS_ONCE(task->task_works);
100+
work = READ_ONCE(task->task_works);
99101
head = !work && (task->flags & PF_EXITING) ?
100102
&work_exited : NULL;
101103
} while (cmpxchg(&task->task_works, work, head) != work);

0 commit comments

Comments
 (0)