1 #include <linux/spinlock.h>
2 #include <linux/task_work.h>
3 #include <linux/tracehook.h>
6 task_work_add(struct task_struct *task, struct callback_head *twork, bool notify)
8 struct callback_head *last, *first;
12 * Not inserting the new work if the task has already passed
13 * exit_task_work() is the responisbility of callers.
15 raw_spin_lock_irqsave(&task->pi_lock, flags);
16 last = task->task_works;
17 first = last ? last->next : twork;
21 task->task_works = twork;
22 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
24 /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */
26 set_notify_resume(task);
30 struct callback_head *
31 task_work_cancel(struct task_struct *task, task_work_func_t func)
34 struct callback_head *last, *res = NULL;
36 raw_spin_lock_irqsave(&task->pi_lock, flags);
37 last = task->task_works;
39 struct callback_head *q = last, *p = q->next;
41 if (p->func == func) {
44 task->task_works = q == p ? NULL : q;
54 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
58 void task_work_run(void)
60 struct task_struct *task = current;
61 struct callback_head *p, *q;
64 raw_spin_lock_irq(&task->pi_lock);
66 task->task_works = NULL;
67 raw_spin_unlock_irq(&task->pi_lock);
72 q = p->next; /* head */
73 p->next = NULL; /* cut it */