Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 2: Process Management and Scheduling


Immediately before a task switch, theprepare_arch_switchhook that must be defined by every archi-
tecture is called fromprepare_task_switch. This enables the kernel to execute architecture-specific code
to prepare for the switch. Most supported architectures (with the exception of Sparc64 and Sparc) do not
use this option because it is not needed.


The context switch proper is performed by invoking two processor-specific functions:



  1. switch_mmchanges the memory context described intask_struct->mm. Depending on the
    processor, this is done by loading the page tables, flushing the translation lookaside buffers
    (partially or fully), and supplying the MMU with new information. Because these actions go
    deep into CPU details, I do not intend to discuss their implementation here.

  2. switch_toswitches the processor register contents and the kernel stack (the virtual user
    address space is changed in the first step, and as it includes the user mode stack, it is not
    necessary to change the latter explicitly). This task also varies greatly from architecture to
    architecture and is usually coded entirely in assembly language. Again, I ignore implemen-
    tation details.
    Because the register contents of the userspace process are saved on the kernel stack when
    kernel mode is entered (see Chapter 14 for details), this need not be done explicitly during
    the context switch. And because each process first begins to execute in kernel mode (at that
    point during scheduling at which control is passed to the new process), the register contents
    are automatically restored using the values on the kernel stack when a return is made to
    userspace.


Remember, however, that kernel threads do not have their own userspace memory context and exe-
cute on top of the address space of a random task; theirtask_struct->mmisNULL. The address space
‘‘borrowed’’ from the current task is noted inactive_mminstead:


kernel/sched.c
if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
...

enter_lazy_tlbnotifies the underlying architecture that exchanging the userspace portion of the virtual
address space is not required. This speeds up the context switch and is known as thelazy TLBtechnique.


If the previous task was a kernel thread (i.e.,prev->mmisNULL), itsactive_mmpointer must be reset to
NULLto disconnect it from the borrowed address space:


kernel/sched.c
if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
rq->prev_mm = oldmm;
}
...
Free download pdf