-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Fri, 31 Oct 2003 21:43:21 +0900 Shinpei Kato <shinny@j02.itscom.net> wrote: >> In 2.4, a process running in the kernel (whether its a normal >> process or a kernel thread) cannot be preempted. It only >> relinquishes the processor when it voluntarily does so. > >You mean a process running in the kernel would be never preempted >unless it relinquishes the processor voluntarily? >If so, I get to have one concern. There are several kernel threads >created at the beginning of kernel processing, aren't there? For >instance, keventd or kapm, etc. >How are they scheduled? I mean how they are switched to another >kernel thread if they doens't have I/O-block or any other block? >Do they have to relinquish the CPU share time voluntarily? But they >wouldn't know when to relinquish, would they? A kernel thread can simply be viewed as a process without user space context. If you look it in this manner it's difficult not to understand that a kernel thread is "passed through the scheduler" just like any other process. For understanding it, take a look at the core of keventd which is the kernel thread which runs the schedule task queue. /* * If one of the functions on a task queue re-adds itself * to the task queue we call schedule() in state TASK_RUNNING */ for (;;) { set_task_state(curtask, TASK_INTERRUPTIBLE); add_wait_queue(&context_task_wq, &wait); if (TQ_ACTIVE(tq_context)) set_task_state(curtask, TASK_RUNNING); schedule(); remove_wait_queue(&context_task_wq, &wait); run_task_queue(&tq_context); wake_up(&context_task_done); if (signal_pending(curtask)) { while (waitpid(-1, (unsigned int *)0, __WALL|WNOHANG) > 0); spin_lock_irq(&curtask->sigmask_lock); flush_signals(curtask); recalc_sigpending(curtask); spin_unlock_irq(&curtask->sigmask_lock); } } As you can see, when keventd is scheduled, it sets its state to TASK_INTERRUPTIBLE, it adds itself in the context_task wait queue. Do not consider the test done by TQ_ACTIVE now. So let's suppose curtask's state is TASK_INTERRUPTIBLE. After doing it, it calls schedule() and so it relinquishes the CPU. In this moment, keventd is not schedulable since it is in TASK_INTERRUPTIBLE state. It will become schedulable when someone/something add a task to the schedule task queue so changing keventd state. Let's see it. F.e. a driver code calls schedule_task(). int schedule_task(struct tq_struct *task) { int ret; need_keventd(__FUNCTION__); ret = queue_task(task, &tq_context); wake_up(&context_task_wq); return ret; } It calls queue_task() which simply enques the task and then wake_up(). This last function has the effect of setting keventd's state to TASK_RUNNING (please walk by yourself through kernel/sched.c). So when there's a scheduled task, keventd MAY be selected by the scheduler. When it will be scheduled in, it will simply run all the enqueued tasks and will repeat the same steps until your machine is up. Hope this helps. Regards. - -- Angelo Dell'Aera 'buffer' Antifork Research, Inc. http://buffer.antifork.org PGP information in e-mail header -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (GNU/Linux) iD8DBQE/orv+pONIzxnBXKIRAoScAJ9x0OHo0dkIgdyDRtNinPiyIBi8HQCeIKrv SfCzKQ7lrk3LL57D13dJSJs= =LurC -----END PGP SIGNATURE----- -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/