1

As explained by several (somewhat old) articles, the Linux idle task (PID=0, one per CPU) is run when there are no other tasks to run. To get the scheduler do this, the idle task must have the lowest priority reserved for it. That old Documentation/ftrace.txt in the linked LWN article explicitly says that

The prio "140" is reserved for the idle task which is the lowest priority thread (pid 0).

This makes sense, but under Linux 4.9

# perf record -e sched:sched_switch sleep 1
# perf script
   sleep  6526 [000] 362661.310842: sched:sched_switch: sleep:6526 [120] S ==> swapper/0:0 [120]

reports a priority of 120 for swapper/0 (in the closing bracket), contradicting the above.

How does the Linux scheduler handle the idle task nowadays? The commits changing ftrace.txt (87d80de28, 294ae4011) didn't help.

1

I got a nice answer from Till Smejkal on the Linux Kernel Mailing List:

The idle task has its own scheduling class that only handles the idle threads per CPU core. This scheduling class has the lowest priority of the scheduling classes available in the kernel. This means that it is the last one in the list of scheduling classes that are asked at a task switch whether they have a task to schedule on the CPU. Hence, the idle task is not managed by CFS and accordingly doesn't have any nice value or priority (or at least it is not important nowadays). Interesting files in the kernel source that might contain more information are kernel/sched/idle_task.c, kernel/sched/sched.h and kernel/sched/core.c.

However, according to my understanding, tasks can have a priority despite not being managed by CFS: realtime tasks (SCHED_FIFO and SCHED_RR) belong to rt_sched_class and certainly have meaningful priorities (as required by POSIX):

static inline int rt_policy(int policy)
{
    return policy == SCHED_FIFO || policy == SCHED_RR;
}

But the main point now is scheduling class priorities, which is implemented by the following const struct sched_class structures being linked by their .next pointers in this order:

stop_sched_class
dl_sched_class
rt_sched_class
fair_sched_class
idle_sched_class

This linked list is walked by (kernel/sched/sched.h)

#ifdef CONFIG_SMP
#define sched_class_highest (&stop_sched_class)
#else
#define sched_class_highest (&dl_sched_class)
#endif
#define for_each_class(class) \
   for (class = sched_class_highest; class; class = class->next)

As alluded to in the above quote, pick_next_task() in kernel/sched/core.c asks each class for a runnable task like this:

again:
    for_each_class(class) {
            p = class->pick_next_task(rq, prev, rf);
            if (p) {
                    if (unlikely(p == RETRY_TASK))
                            goto again;
                    return p;
            }
    }

All this means that the idle tasks happen to have a priority value (some default), but it's never consulted during scheduling decisions, because they are the only tasks (pinned to particular CPUs) in idle_sched_class.

The above leaves the question of the changed priority value open, but that's mostly of historical significance by now (the above code quotes are from Linux 4.16).

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.