2 * linux/kernel/context.c
4 * Mechanism for running arbitrary tasks in process context
9 #define __KERNEL_SYSCALLS__
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/init.h>
15 #include <linux/unistd.h>
16 #include <linux/signal.h>
18 static DECLARE_TASK_QUEUE(tq_context
);
19 static DECLARE_WAIT_QUEUE_HEAD(context_task_wq
);
20 static int keventd_running
;
22 void schedule_task(struct tq_struct
*task
)
24 if (keventd_running
== 0)
25 printk(KERN_ERR
"schedule_task(): keventd has not started\n");
26 queue_task(task
, &tq_context
);
27 wake_up(&context_task_wq
);
30 EXPORT_SYMBOL(schedule_task
);
32 static int context_thread(void *dummy
)
34 struct task_struct
*curtask
= current
;
35 DECLARE_WAITQUEUE(wait
, curtask
);
36 struct k_sigaction sa
;
39 strcpy(curtask
->comm
, "keventd");
42 spin_lock_irq(&curtask
->sigmask_lock
);
43 siginitsetinv(&curtask
->blocked
, sigmask(SIGCHLD
));
44 recalc_sigpending(curtask
);
45 spin_unlock_irq(&curtask
->sigmask_lock
);
47 /* Install a handler so SIGCLD is delivered */
48 sa
.sa
.sa_handler
= SIG_IGN
;
50 siginitset(&sa
.sa
.sa_mask
, sigmask(SIGCHLD
));
51 do_sigaction(SIGCHLD
, &sa
, (struct k_sigaction
*)0);
54 __set_task_state(curtask
, TASK_INTERRUPTIBLE
);
55 add_wait_queue(&context_task_wq
, &wait
);
58 * Careful: we depend on the wait-queue modifications
59 * to also act as memory barriers.
64 remove_wait_queue(&context_task_wq
, &wait
);
65 __set_task_state(curtask
, TASK_RUNNING
);
66 run_task_queue(&tq_context
);
67 if (signal_pending(curtask
)) {
68 while (waitpid(-1, (unsigned int *)0, __WALL
|WNOHANG
) > 0)
70 flush_signals(curtask
);
71 recalc_sigpending(curtask
);
76 int start_context_thread(void)
78 kernel_thread(context_thread
, NULL
, CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
);