#define switch_to(n) {\
struct {long a,b;} __tmp; \
__asm__("cmpl %%ecx,current\n\t" \
"je 1f\n\t" \
"movw %%dx,%1\n\t" \
"xchgl %%ecx,current\n\t" \
"ljmp *%0\n\t" \
"cmpl %%ecx,last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:" \
::"m" (*&__tmp.a),"m" (*&__tmp.b), \
"d" (_TSS(n)),"c" ((long) task[n])); \
}
上面的嵌入宏汇编代码就是完成任务的切换操作。首先判断传递进来的任务号n是否是当前任务,如果是就跳出,否则将current指向task[n],然后长跳转任务n的TSS选择符,这样就完成了任务切换操作。
注意:
1. 跳转到TSS段选择符会造成任务切换到该TSS对应的进程。
2. 对于造成任务切换的长跳转,TSS段基址无用。
在保护模式下CPU进行长跳转,如果发现段选择符指向TSS段,那么CPU将会自动将TSS段的内容加载到当前CPU寄存器中,比如eax,ldr,cs,ss,esp等等,其实就是104字节的TSS结构的所有成员变量赋值给CPU寄存器(注意这里是ss0和esp0)。再次强调这个过程是自动完成的。进程TSS结构的初始值在copy_process函数中完成,最后调用