您的位置:首页 > 运维架构 > Linux

《深入理解Linux内核3rd》学习笔记——进程切换(下):switch_to宏、__switch_to函数

2010-06-02 20:37 363 查看
switch_to宏

  switch_to宏代码如下,其中,prev是即将要被换出CPU的进程的描述符,next是即将得到CPU的进程的描述符。

__switch_to

struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
int cpu = smp_processor_id(); /* 得到当前代码运行的CPU编号 */
struct tss_struct *tss = &per_cpu(init_tss, cpu); /* 得到当前CPU的TSS */

/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */

__unlazy_fpu(prev_p); /* 加载FPU、MMX、XMM的寄存器组 */

/*
* Reload esp0, LDT and the page table pointer:
*/
load_esp0(tss, next); /* 加载next的esp0到tss的esp0中 */

/*
* Load the per-thread Thread-Local Storage descriptor.
*/
load_TLS(next, cpu); /* 加载next的TLS到CPU的GDT的TLS中 */

/*
* Save away %fs and %gs. No need to save %es and %ds, as
* those are always kernel segments while inside the kernel.
*/
asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs)); /* 保存prev的fs寄存器 */
asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs)); /* 保存prev的gs寄存器 */

/*
* Restore %fs and %gs if needed.
*/
if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) {
loadsegment(fs, next->fs); /* 加载fs寄存器 */
loadsegment(gs, next->gs); /* 加载gs寄存器 */
}

/*
* Now maybe reload the debug registers
*/
if (unlikely(next->debugreg[7])) {
loaddebug(next, 0); /* 从next的thread_struct结构中加载调试信息到dr0-dr7寄存器 */
loaddebug(next, 1);
loaddebug(next, 2);
loaddebug(next, 3);
/* no 4 and 5 */
loaddebug(next, 6);
loaddebug(next, 7);
}

if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
handle_io_bitmap(next, tss); /* 从next得到IO允许位,并跟新tss->io_bitmap_base字段 */

return prev_p;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: