我写了一个简单的合作多线程库。目前,我总是在切换到新上下文时使用fxsave
/ fxrstor
保存和恢复fpu状态。但这在cdecl调用约定中是否必要?
举个简单的例子:
float thread_using_fpu(float x)
{
float y = x / 2; // do some fpu operation
yield(); // context switch, possibly altering fpu state.
y = y / 2; // another fpu operation
return y;
}
编译器调用yield()
后可能会对FPU状态做出任何假设吗?
答案 0 :(得分:3)
根据SYSTEM V APPLICATION BINARY INTERFACE Intel386TM Architecture Processor Supplement,第3-12页:
%st(0):如果函数没有返回浮点值,那么这个 注册必须为空。此寄存器必须为空 进入一个功能。
%st(1)到%st(7): 浮点临时寄存器在中没有指定的作用 标准呼叫序列。输入前这些寄存器必须为空 退出某个职能部门。
因此,您无需上下文切换它们。
另一个,newer version说:
进入某个功能后,CPU应处于x87模式。因此,每个使用MMX寄存器的函数都需要发出 返回之前使用MMX寄存器后的emms或femms指令 或者调用另一个函数。 [...] MXCSR寄存器的控制位是被调用者保存的(保留在调用之间),而状态位是调用者保存的(不保留)。 x87状态字寄存器是调用者保存的,而x87控件 单词是被调用者保存的。 [...]所有x87寄存器都被调用者保存,因此使用MMX寄存器的被调用者可以使用更快的femms指令。
因此,您可能需要保存控制字。
答案 1 :(得分:2)
没有。您无需保存状态。如果一个线程处于浮点计算的中间,例如,设置了非规范化的标志,并且该线程被中断,那么当它恢复时,O / S或内核将设置标志,就像它将恢复一样其他登记册。同样,您不必在yield()中担心它。
编辑:如果您正在进行自己的上下文切换,则可能需要保存精度和舍入控制标志(如果需要将它们设置为非默认值)。否则,你再次没事。