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