static inline
task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next)
{
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
WARN_ON(rq->prev_mm);
rq->prev_mm = oldmm;
}
/* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
return prev;
}
可以看出进程切换
1.内存地址空间切换
2.register ,内核栈的切换
#define switch_to(prev,next,last) do { /
unsigned long esi,edi; /
asm volatile("pushfl/n/t" /
"pushl %%ebp/n/t" /
"movl %%esp,%0/n/t" /* save ESP */ /
"movl %5,%%esp/n/t" /* restore ESP */ /
"movl $1f,%1/n/t" /* save EIP */ /
"pushl %6/n/t" /* restore EIP */ /
"jmp __switch_to/n" /
"1:/t" /
"popl %%ebp/n/t" /
"popfl" /
:"=m" (prev->thread.esp),"=m" (prev->thread.eip), /
"=a" (last),"=S" (esi),"=D" (edi) /
:"m" (next->thread.esp),"m" (next->thread.eip), /
"2" (prev), "d" (next)); /
} while (0)
1.将 eflags 压栈
2.将 内核栈地址压栈
3.指令指针压栈
切换前 将 prev 局部变量(内核栈内) 写 eax
切换后将 prev 赋值为 eax;
c: prev =c,next =a;
a: prev =a,next =b
切换后
a: prev =c,next=b