Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 2: Process Management and Scheduling


points to thecurrentlyrunning process, whilenextpoints to the process that will be running next. To
perform the switch fromprevtonext, the first two arguments are completely sufficient forswitch_to.
For process A,prevpoints to A andnextpoints to B.

A problem arises when A is selected to execute again. Control will return to the point afterswitch_to,
and if the stack were restored to the exact state it had before the switch,prevandnextwould still point
to the same values as before the switch — namely,next=Bandprev=A.Inthissituation,thekernelwould
not know that process C has actually run before process A.

Therefore, the low-level task switch routinemust feed the previously executing task tocontext_switch
when a new task is selected. Since control flow comes back to the middle of the function, this cannot be
done with regular function return values, and that is why a three-parametermacrois used. However, the
conceptional effect is the same as ifswitch_towere a function of two arguments that would return a
pointer to the previously executing process. Whatswitch_toessentially does is

prev = switch_to(prev,next)

where theprevvalue returned isnottheprevvalue used as the argument, but the process that executed
last in time. In the above example, process A would feedswitch_towithAandB, but would obtain
prev=Cas result. How the kernel implements this behavior depends on the underlying architecture, but
it is obvious that the kernel can reconstruct the desired information by considering the kernel mode
stacks of both processes — which are naturally simultaneously available to the kernel, which can access
all memory at will.

Lazy FPU Mode


Because the speed of context switching plays a major role in system performance, the kernel uses a trick
to reduce the CPU time needed. Floating-point registers (and other extended registers not used by the
kernel; e.g., the SSE2 registers on IA-32 platforms) are not saved unless they are actually used by the
application and are not restored unless they are required. This is known as thelazy FPUtechnique. Its
implementation differs from platform to platform because assembly language code is used, but the basic
principle is always the same. It should also be noted that, regardless of platform, the contents of the
floating-point registers arenotsaved on the process stack but in its thread data structure. I illustrate this
technique by means of an example.

For the sake of simplicity, let us assume this time that there are only two processes, A and B, on the
system. Process A is running and uses floating-point operations. When the scheduler switches to process
B, the contents of the floating-point registers of A are saved in the thread data structure of the process.
However, the values in these registers arenotimmediately replaced with the values for process B.

If B does not perform any floating-point operations during its time slice, A sees its former register con-
tents when it is next activated. The kernel is therefore spared the effort of explicitly restoring register
values, and this represents a time-saving.

If, however, B does perform floating-point operations, this fact is reported to the kernel so that it can
fill the registers with the appropriate values from the thread data structure. Consequently, the kernel
saves and restores floating-point register contents only when needed and wastes no time on superfluous
operations.
Free download pdf