switch_to

switch_to

Content #

//include/linux/sched.h

#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])); \
}

“m” (*&__tmp.a)​​ #

表示将__tmp.a的内存地址作为输入操作数(%0),但​​并未显式赋值​​。实际使用时,__tmp.a的值是​​未初始化的随机值​​(取决于栈状态),但代码中仅利用了它的​​内存地址​​,而非其内容。

movw %%dx, %1​​ #

这条指令将%%dx(TSS选择子)写入__tmp.b的低16位(%1对应__tmp.b)。注意:__tmp.a和__tmp.b是连续内存(结构体成员),movw %%dx, %1可能覆盖__tmp.a的部分内容(取决于对齐),但代码逻辑并不依赖__tmp.a的具体值。

为什么不需要显式设置 __tmp.a?​​ #

​​硬件任务切换的特性​​: ljmp到TSS选择子时,CPU会直接加载TSS中的状态(包括EIP),​​完全忽略远跳转指令中的偏移量​​。因此__tmp.a的值(偏移部分)不会被使用。​​代码优化​​:显式初始化__tmp.a是多余的(如movl $0, %0),故省略以提升性能。

From #