Here is a copy of the relevant code from /usr/src/linux/kernel/sched.c, annotated and abridged.
The process table is an array of pointers to struct task_struct structures. See /usr/include/linux/sched.h for the definition of this structure.
If a process has a timeout and has reached it, then jiffies (the number of 100th's of a second since system start) will have passed timeout. timeout was originally set as jiffies + desired_timeout.
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.
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.)
If there is no process in this slot then don't bother...
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.
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 break; line.
sti() enables interrupts again, and switch_to() (defined in linux/sched.h) sets things up so that when we return to ret_to_sys_call(), we will return from ret_to_sys_call() into the new process.
I have truncated do_timer() extremely, only showing the pieces that relate specifically to schedule(). For information on the rest, see the appropriate section. For instance, for commentary on the itimer mechanism see the section on itimers. [I suppose I need to write that section now...I will need to put a reference here to that section.] I have specifically left out all the accounting stuff, all the timer stuff, and the floppy timer.
Here is where jiffies 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.
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 need_resched flag if necessary so that schedule gets called again as soon as possible.