3
votes

I have created a kernel thread using kthread_run in a kernel module. The thread is very simple, just like bellow.

static  int my_thread_func(void * data)
{
    int a;
    DBG_PRINT("policy:%lu; prio:%d", current->policy, current->prio);
    while (!kthread_should_stop()) 
    {
        a++;
    }
}

However, after I loaded the module, the system did not response any more.

So I wonder what's the schedule policy and priority of this kernel thread. Then I try to print out the schedule policy and priority of this kernel thread, and got bellow output.

policy:0; prio:120

policy:0 means SCHED_NORMAL;
prio:120 this is also not high.

While the thread does not have a SCHED_FIFO or SCHED_RR schedule policy, Why can it hog up the cpu?

And I also found that if I insert some sleep code in the loop body of the thread, the system could remain responsive.

And I also found when I run a userspace program implemented as bellow, the system remained responsive, too.

int main(int argc, char *argv[])
{
    int a;
    while (1) a++;
    return 0;
}

So who can tell me, why the kernel thread could hog up the cpu.

1
Your kernel thread doesn't ever yield control (wait_event_interruptible and friends), so of course it will prevent events from being processed. It also does not process signals. - Michael Foukarakis
But the schedule policy of the kernel thread is SCHED_NORMAL, not SCHED_FIFO or SCHED_RR, so once the kernel thread runs out its time slice, other tasks shall have chance to run. - sunmingbao
Only if you are yielding control to the kernel, which you are not. - Michael Foukarakis
In my understanding, the kernel thread shall be interrupted by timer interrupt. And in the timer interrupt processing, kernel has chance to examine the thread's time slice, and call schedule to select an other task to run. - sunmingbao

1 Answers

2
votes

When you say the priority is 120, are you observing the priority of kthreadd, or the actual kernel thread that was created for you?

Please see http://lxr.free-electrons.com/source/kernel/kthread.c#L310 for the function that is used to create new kernel threads.

Excerpt:

struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
                                           void *data, int node,
                                           const char namefmt[],
                                           ...)
{
    ...
        if (!IS_ERR(task)) {
                static const struct sched_param param = { .sched_priority = 0 };
                ...
                /*
                 * root may have changed our (kthreadd's) priority or CPU mask.
                 * The kernel thread should not inherit these properties.
                 */
                sched_setscheduler_nocheck(task, SCHED_NORMAL, &param);
                set_cpus_allowed_ptr(task, cpu_all_mask);
        }
    ...
}

It appears that the sched_priority is set to 0.

Now, please look at http://lxr.free-electrons.com/source/include/linux/sched/prio.h#L9

Excerpt:

/*
 * Priority of a process goes from 0..MAX_PRIO-1, valid RT
 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
 * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
 * values are inverted: lower p->prio value means higher priority.
 *
 * The MAX_USER_RT_PRIO value allows the actual maximum
 * RT priority to be separate from the value exported to
 * user-space.  This allows kernel threads to set their
 * priority to a value higher than any user task. Note:
 * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
*/

Please note the second paragraph: This allows kernel threads to set their priority to a value higher than any user task.

Summary:

It appears that newly created kernel threads are set to sched_priority of 0 even with SCHED_NORMAL. Priority of 0 is not a normal priority for SCHED_NORMAL, and thus the kernel thread will take priority over any other thread (that isn't using an RT policy---and I don't think any processes in the kernel use RT by default).

Addendum:

Note: I am not 100% sure if this is the reason. But, if you look at the comments in the kernel for kernel threads, they all seem to imply that a kernel thread keeps running UNLESS:

  • The kernel thread itself yields or calls do_exit.
  • Someone else calls kthread_should_stop().

Which to me, sounds like the kernel thread runs as long as it wants, until it decides to stop, or someone else explicitly tells it to stop.