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 */