This source file includes following definitions.
- task_work_add
- task_work_cancel
- task_work_run
1
2 #include <linux/spinlock.h>
3 #include <linux/task_work.h>
4 #include <linux/tracehook.h>
5
6 static struct callback_head work_exited;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 int
28 task_work_add(struct task_struct *task, struct callback_head *work, bool notify)
29 {
30 struct callback_head *head;
31
32 do {
33 head = READ_ONCE(task->task_works);
34 if (unlikely(head == &work_exited))
35 return -ESRCH;
36 work->next = head;
37 } while (cmpxchg(&task->task_works, head, work) != head);
38
39 if (notify)
40 set_notify_resume(task);
41 return 0;
42 }
43
44
45
46
47
48
49
50
51
52
53
54
55 struct callback_head *
56 task_work_cancel(struct task_struct *task, task_work_func_t func)
57 {
58 struct callback_head **pprev = &task->task_works;
59 struct callback_head *work;
60 unsigned long flags;
61
62 if (likely(!task->task_works))
63 return NULL;
64
65
66
67
68
69
70 raw_spin_lock_irqsave(&task->pi_lock, flags);
71 while ((work = READ_ONCE(*pprev))) {
72 if (work->func != func)
73 pprev = &work->next;
74 else if (cmpxchg(pprev, work, work->next) == work)
75 break;
76 }
77 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
78
79 return work;
80 }
81
82
83
84
85
86
87
88
89
90 void task_work_run(void)
91 {
92 struct task_struct *task = current;
93 struct callback_head *work, *head, *next;
94
95 for (;;) {
96
97
98
99
100 raw_spin_lock_irq(&task->pi_lock);
101 do {
102 work = READ_ONCE(task->task_works);
103 head = !work && (task->flags & PF_EXITING) ?
104 &work_exited : NULL;
105 } while (cmpxchg(&task->task_works, work, head) != work);
106 raw_spin_unlock_irq(&task->pi_lock);
107
108 if (!work)
109 break;
110
111 do {
112 next = work->next;
113 work->func(work);
114 work = next;
115 cond_resched();
116 } while (work);
117 }
118 }