1
2
3
4
5
6
7
8
9
10
11
12
13
14#define __KERNEL_SYSCALLS__
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/init.h>
20#include <linux/unistd.h>
21#include <linux/signal.h>
22#include <linux/completion.h>
23
24static DECLARE_TASK_QUEUE(tq_context);
25static DECLARE_WAIT_QUEUE_HEAD(context_task_wq);
26static DECLARE_WAIT_QUEUE_HEAD(context_task_done);
27static int keventd_running;
28static struct task_struct *keventd_task;
29
30static int need_keventd(const char *who)
31{
32 if (keventd_running == 0)
33 printk(KERN_ERR "%s(): keventd has not started\n", who);
34 return keventd_running;
35}
36
37int current_is_keventd(void)
38{
39 int ret = 0;
40 if (need_keventd(__FUNCTION__))
41 ret = (current == keventd_task);
42 return ret;
43}
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58int schedule_task(struct tq_struct *task)
59{
60 int ret;
61 need_keventd(__FUNCTION__);
62 ret = queue_task(task, &tq_context);
63 wake_up(&context_task_wq);
64 return ret;
65}
66
67static int context_thread(void *startup)
68{
69 struct task_struct *curtask = current;
70 DECLARE_WAITQUEUE(wait, curtask);
71 struct k_sigaction sa;
72
73 daemonize();
74 strcpy(curtask->comm, "keventd");
75 keventd_running = 1;
76 keventd_task = curtask;
77
78 spin_lock_irq(&curtask->sigmask_lock);
79 siginitsetinv(&curtask->blocked, sigmask(SIGCHLD));
80 recalc_sigpending(curtask);
81 spin_unlock_irq(&curtask->sigmask_lock);
82
83 complete((struct completion *)startup);
84
85
86 sa.sa.sa_handler = SIG_IGN;
87 sa.sa.sa_flags = 0;
88 siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
89 do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
90
91
92
93
94
95 for (;;) {
96 set_task_state(curtask, TASK_INTERRUPTIBLE);
97 add_wait_queue(&context_task_wq, &wait);
98 if (TQ_ACTIVE(tq_context))
99 set_task_state(curtask, TASK_RUNNING);
100 schedule();
101 remove_wait_queue(&context_task_wq, &wait);
102 run_task_queue(&tq_context);
103 wake_up(&context_task_done);
104 if (signal_pending(curtask)) {
105 while (waitpid(-1, (unsigned int *)0, __WALL|WNOHANG) > 0)
106 ;
107 spin_lock_irq(&curtask->sigmask_lock);
108 flush_signals(curtask);
109 recalc_sigpending(curtask);
110 spin_unlock_irq(&curtask->sigmask_lock);
111 }
112 }
113}
114
115
116
117
118
119
120
121
122
123
124
125
126
127static struct tq_struct dummy_task;
128
129void flush_scheduled_tasks(void)
130{
131 int count;
132 DECLARE_WAITQUEUE(wait, current);
133
134
135
136
137
138
139
140
141 add_wait_queue(&context_task_done, &wait);
142 for (count = 0; count < 2; count++) {
143 set_current_state(TASK_UNINTERRUPTIBLE);
144
145
146 schedule_task(&dummy_task);
147
148
149 schedule();
150 }
151 remove_wait_queue(&context_task_done, &wait);
152}
153
154int start_context_thread(void)
155{
156 static struct completion startup __initdata = COMPLETION_INITIALIZER(startup);
157
158 kernel_thread(context_thread, &startup, CLONE_FS | CLONE_FILES);
159 wait_for_completion(&startup);
160 return 0;
161}
162
163EXPORT_SYMBOL(schedule_task);
164EXPORT_SYMBOL(flush_scheduled_tasks);
165
166