The code

Here is a copy of the relevant code from /usr/src/linux/kernel/sched.c, annotated and abridged.

#screen1726#

The process table is an array of pointers to <#1728#> struct task_struct<#1728#> structures. See /usr/include/linux/sched.h for the definition of this structure.

#screen1729#

If a process has a timeout and has reached it, then <#1731#> jiffies<#1731#> (the number of 100ths of a second since system start) will have passed <#1732#> timeout<#1732#>. <#1733#> timeout<#1733#> was originally set as <#1734#> jiffies + desired_timeout<#1734#>.

#screen1735#

If the process has been sent a signal, and is no longer blocked, then let the process be allowed to run again, when its turn comes.

#screen1737#

At this point, all runnable processes have been flagged as runnable, and we are ready to choose one to run, by running through the process table. What we are looking for is the process with the largest counter. The counter for each runnable process is incremented each time the scheduler is called by an amount that is weighted by the priority, which is the kernel version of the `nice' value. (It differs in that the priority is never negative.)

#screen1739#

If there is no process in this slot then don't bother...

#screen1741#

If the counter is higher than any previous counter, then make the process the next process, unless, of course, an even higher one is encountered later in the loop.

#screen1743#

Here is where the counter is set. It is first divided by 2, and then the priority is added. Note that this happens only if no process has been found to switch to, because of the <#1745#> break;<#1745#> line.

#screen1746#

<#1748#> sti()<#1748#> enables interrupts again, and <#1749#> switch_to()<#1749#> (defined in linux/sched.h) sets things up so that when we return to <#1750#> ret_to_sys_call()<#1750#>, we will return from <#1751#> ret_to_sys_call()<#1751#> into the <#1752#> new<#1752#> process. I have truncated <#1753#> do_timer()<#1753#> extremely, only showing the pieces that relate specifically to <#1754#> schedule()<#1754#>. For information on the rest, see the appropriate section. For instance, for commentary on the <#1755#> itimer<#1755#> mechanism see the section on <#1756#> itimers<#1756#>. <#1764#> [I suppose I need to <#1757#> write<#1757#> that section now... I will need to put a reference here to that section.]<#1764#> I have specifically left out all the accounting stuff, all the timer stuff, and the floppy timer.

#screen1758#

Here is where <#1760#> jiffies<#1760#> is incremented. This is all-important to the rest of the kernel, because all time calculations (except for timed delay loops) are based on this variable.

#screen1761#

Don't let task 0 run if anything else can run, because task 0 doesn't do anything. If task 0 is running, the machine is idle, but don't let it be idle if anything else is happening, so run schedudule as soon as possible. Set the <#1763#> need_resched<#1763#> flag if necessary so that schedule gets called again as soon as possible. % %