diff options
| author | Petr Mladek <pmladek@suse.com> | 2022-12-08 11:46:56 +0100 |
|---|---|---|
| committer | Petr Mladek <pmladek@suse.com> | 2022-12-08 11:46:56 +0100 |
| commit | 6b2b0d839acaa84f05a77184370f793752e786e9 (patch) | |
| tree | d051c2ca80acc8a442277410d23a2053685f8a85 /kernel/task_work.c | |
| parent | 7365df19e8ff7a031e1557616fc0b3aa6d794d7e (diff) | |
| parent | 5074ffbec67ac592614901771d3a15e1198d759d (diff) | |
Merge branch 'rework/console-list-lock' into for-linus
Diffstat (limited to 'kernel/task_work.c')
| -rw-r--r-- | kernel/task_work.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/kernel/task_work.c b/kernel/task_work.c index dff75bcde151..065e1ef8fc8d 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -47,12 +47,12 @@ int task_work_add(struct task_struct *task, struct callback_head *work, /* record the work call stack in order to print it in KASAN reports */ kasan_record_aux_stack(work); + head = READ_ONCE(task->task_works); do { - head = READ_ONCE(task->task_works); if (unlikely(head == &work_exited)) return -ESRCH; work->next = head; - } while (cmpxchg(&task->task_works, head, work) != head); + } while (!try_cmpxchg(&task->task_works, &head, work)); switch (notify) { case TWA_NONE: @@ -100,10 +100,12 @@ task_work_cancel_match(struct task_struct *task, * we raced with task_work_run(), *pprev == NULL/exited. */ raw_spin_lock_irqsave(&task->pi_lock, flags); - while ((work = READ_ONCE(*pprev))) { - if (!match(work, data)) + work = READ_ONCE(*pprev); + while (work) { + if (!match(work, data)) { pprev = &work->next; - else if (cmpxchg(pprev, work, work->next) == work) + work = READ_ONCE(*pprev); + } else if (try_cmpxchg(pprev, &work, work->next)) break; } raw_spin_unlock_irqrestore(&task->pi_lock, flags); @@ -151,16 +153,16 @@ void task_work_run(void) * work->func() can do task_work_add(), do not set * work_exited unless the list is empty. */ + work = READ_ONCE(task->task_works); do { head = NULL; - work = READ_ONCE(task->task_works); if (!work) { if (task->flags & PF_EXITING) head = &work_exited; else break; } - } while (cmpxchg(&task->task_works, work, head) != work); + } while (!try_cmpxchg(&task->task_works, &work, head)); if (!work) break; |
