If you’re writing a kernel, you will need to consider different methods of task scheduling, because your OS can, hopefully, run more than one program.<p/>

The simplest form of task scheduling is to simply run one program at once. This is how DOS worked – it gives you the nice DOS prompt, and then when you run a program, it looks to the OS like it is making a function call. The program does whatever it does, and when it finally returns, the OS has control again. The only other place the OS gets control is during an interrupt or syscall – interrupt handlers are registered for lots of different stuff, hardware and software, and whenever one is triggered, the interrupt handler executes on the borrowed stack of whatever thread was executing at the time of the interrupt.<p/>

So that’s great and wonderful, and then when a program goes into an infinite loop… you can reboot your computer. Sry!<p/>

Okay, let’s do something a little more complex. Examine the previous model, but note: whenever one program makes a system call, or we see an interrupt, we now are executing OS code again. Our change will be that, rather than simply giving the stack and processor back to the program after this task is done, we can do several things – switch to another task, do some of our own processing, etc. Eventually, when we decide that the first program is good to run, we will jump into it again.<p/>

Lots of programs make system calls all the time, so this model can be pretty useful. But it still doesn’t solve pathological cases where the program goes into an infinite loop and doesn’t make any system calls – execution is still stuck in the program and you’re going to have to reboot. (Perhaps you can wait for the user to generate interrupts, notice that the system is probably stuck in a loop, and switch away from the task. I wouldn’t rely on it, though…)<p/>

Okay, so let’s generate that interrupt ourselves. Before we give control to a task, we’ll set an alarm for 50 milliseconds in the future. When we see this alarm, if the task is still running, stop running it and run something else. This, my friend, is preemptive multitasking – the program cannot control when it is subjected to timeslicing.<p/>

And, of course, you can be smart about how big of a timeslice you give different processes, and in what order they run. Linux decides based on several things – the process nice value, the “interactivity” of the process (how long it spends sleeping as opposed to working), etc. But the basic premise is still there.<p/>