《深入理解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;
}
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;
}
相关文章推荐
- 《深入理解Linux内核3rd》学习笔记——进程切换(上):相关知识
- Linux内核switch_to宏实现进程切换的原理
- 《深入理解Linux内核3rd》学习笔记——进程切换(上):相关知识
- 进程切换switch_to宏第三个参数分析
- switch_to宏第3个参数分析
- 【内核】进程切换 switch_to 与 __switch_to
- switch_to宏
- linux内核V2.6.11学习笔记(3)--switch_to宏
- switch_to宏为什么要三个参数
- 《深入理解Linux内核3rd》学习笔记——进程描述符
- linux内核switch_to函数
- 《深入理解Linux内核3rd》学习笔记——进程描述符
- 【内核】进程切换 switch_to 与 __switch_to
- 《深入理解Linux内核3rd》学习笔记——初始化临时页表
- 具体分析contrex-A9的汇编代码__switch_to(进程切换)
- 详细分析contrex-A9的汇编代码__switch_to(进程切换)
- linux下的schedule()函数详解,以及进程的调度,current_thread_info,switch_to宏等笔记
- switch_to宏为什么要三个参数
- 【内核】进程切换 switch_to 与 __switch_to
- 分析进程切换宏 switch_to