fbcon: fix race condition between console lock and cursor timer
[deliverable/linux.git] / kernel / task_work.c
CommitLineData
e73f8959
ON
1#include <linux/spinlock.h>
2#include <linux/task_work.h>
3#include <linux/tracehook.h>
4
5int
67d12145 6task_work_add(struct task_struct *task, struct callback_head *twork, bool notify)
e73f8959 7{
ed3e694d 8 struct callback_head *last, *first;
e73f8959 9 unsigned long flags;
e73f8959 10
e73f8959 11 /*
ed3e694d
AV
12 * Not inserting the new work if the task has already passed
13 * exit_task_work() is the responisbility of callers.
e73f8959
ON
14 */
15 raw_spin_lock_irqsave(&task->pi_lock, flags);
ed3e694d
AV
16 last = task->task_works;
17 first = last ? last->next : twork;
18 twork->next = first;
19 if (last)
20 last->next = twork;
21 task->task_works = twork;
e73f8959
ON
22 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
23
24 /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */
ed3e694d 25 if (notify)
e73f8959 26 set_notify_resume(task);
ed3e694d 27 return 0;
e73f8959
ON
28}
29
67d12145 30struct callback_head *
e73f8959
ON
31task_work_cancel(struct task_struct *task, task_work_func_t func)
32{
33 unsigned long flags;
67d12145 34 struct callback_head *last, *res = NULL;
e73f8959
ON
35
36 raw_spin_lock_irqsave(&task->pi_lock, flags);
158e1645
AV
37 last = task->task_works;
38 if (last) {
67d12145 39 struct callback_head *q = last, *p = q->next;
158e1645
AV
40 while (1) {
41 if (p->func == func) {
42 q->next = p->next;
43 if (p == last)
44 task->task_works = q == p ? NULL : q;
45 res = p;
46 break;
47 }
48 if (p == last)
49 break;
50 q = p;
51 p = q->next;
e73f8959
ON
52 }
53 }
e73f8959 54 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
158e1645 55 return res;
e73f8959
ON
56}
57
58void task_work_run(void)
59{
60 struct task_struct *task = current;
67d12145 61 struct callback_head *p, *q;
e73f8959 62
a2d4c71d
AV
63 while (1) {
64 raw_spin_lock_irq(&task->pi_lock);
65 p = task->task_works;
66 task->task_works = NULL;
67 raw_spin_unlock_irq(&task->pi_lock);
e73f8959 68
a2d4c71d
AV
69 if (unlikely(!p))
70 return;
e73f8959 71
a2d4c71d
AV
72 q = p->next; /* head */
73 p->next = NULL; /* cut it */
74 while (q) {
75 p = q->next;
76 q->func(q);
77 q = p;
78 }
e73f8959
ON
79 }
80}
This page took 0.045079 seconds and 5 git commands to generate.