在x86-64下切换堆栈的最小代码是什么?我试图在Windows和Linux下实现光纤,而不使用getcontext或setjmp +内联程序集。它真的像交换$rsp和$rbp一样简单吗?因为我可以很容易地做到这一点。我只是不知道该怎么做。我对我的x86-64知识已经生疏了。
发布于 2018-03-28 22:44:05
将RSP更改为指向不同的堆栈必须作为上下文切换的一部分来完成,它保存旧线程/光纤中的所有寄存器,并从新寄存器加载保存的体系结构状态。不仅是RBP,而且所有的RAX和R8-R15,以及RIP (通过jmp或ret)。和所有其他调用保存的体系结构状态,包括xmm6-15在Windowsx86-64上,我认为。如果您的代码曾经更改过MXCSR或x87控件寄存器,您也需要保存/恢复它们。
但是,如果您将上下文切换放到一个noinline 函数中,编译器将为一个常规函数调用(实际上在很晚的时间内返回)编写代码,而函数调用已经关闭了所有调用失败的寄存器。您不必保存调用方的zmm0-31或MPX bnd寄存器或RFLAGS。因此,可能不值得使用xsaveopt / xrstor来保存FPU / SIMD状态。
如果您不修改其他的规则,您将有一个坏的时间,因为切换到一个新的堆栈和新代码与旧寄存器基本上是相同的事情,破坏调用保存的寄存器从编译器,即违反ABI。
您不需要保存RFLAGS,因为在用户空间中唯一可以改变的是条件代码,而这些条件代码都是调用失败的。ABI /调用约定已经要求DF在函数调用/返回时是明确的。
发布于 2018-04-04 07:12:12
上下文切换由ABI确定(必须保留被调用保存的寄存器)。boost.context已经为几个体系结构提供了一个实现。boost.fiber是基于boost.context的for::类线程API的纤维抽象。
发布于 2018-03-28 22:20:47
微软确实提供了西杰普、setjmp3和龙虾。他们还提供使用setjmp/longjmp。
下面的代码示例可以在用示例解释标准C库中的setjmp()和longjmp()函数上找到
/* setjmp_longjmp.c -- program handles error through 'setjmp()' */
/* and longjmp() */
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
/* declare variable of type jmp_buf */
jmp_buf resume_here;
void hello(void);
int main(void)
{
int ret_val;
/* Initialize 'resume_here' by calling setjmp() */
if (setjmp(resume_here)) {
printf("After \'longjump()\', back in \'main()\'\n");
printf("\'jump buffer variable \'resume_here\'\' becomes "
"INVALID!\n");
}
else {
printf("\'setjmp()\' returns first time\n");
hello();
}
return 0;
}
void hello(void)
{
printf("Hey, I'm in \'hello()\'\n");
longjmp(resume_here, 1);
/* other code */
printf("can't be reached here because I did longjmp!\n");
}https://stackoverflow.com/questions/49542648
复制相似问题