none
x64环境下实现的协程,setjmp后切换堆栈,longjmp时候会异常 RRS feed

  • 问题

  • 源码如下(使用VS继承的clang编译器):

    #include <stdint.h>
    #include <stdio.h>
    #include <setjmp.h>
    
    #if     defined(_WIN64)
    static __inline__ __attribute__((__always_inline__))
    void task_set_stack(uintptr_t stack)
    {
        __asm__("movq %0, %%rsp" : : "r"(stack));
    }
    #elif   defined(_WIN32)
    static __inline__ __attribute__((__always_inline__))
    void task_set_stack(uintptr_t stack)
    {
        __asm__("movl %0, %%esp" : : "r"(stack));
    }
    #else
    #   error "not supported"
    #endif
    
    struct task_t {
        jmp_buf *ret;               // for return to scheduler
        jmp_buf *pos;               // for go back from scheduler
        uint32_t stack_size;
        uint64_t stack[32 * 1024] __attribute__((__aligned__(16)));
    };
    
    static void __task_entry(struct task_t *task)
    {
        printf("task is running...\n");
        longjmp(*(task->ret), -1);
    }
    
    struct task_t task = {
        .stack_size = sizeof(task.stack),
    };
    
    int main()
    {
        jmp_buf ret;
        task.ret = &ret;
        if (!setjmp(ret)) {
            task_set_stack((uintptr_t)(&task.stack[task.stack_size >> 3]));
            __task_entry(&task);
        } else {
            printf("back from task...\n");
        }
        return 0;
    }
    

    在arm/win_x86/linux_x86/linux_x64下都可以使用,以上代码只是演示问题,并非协程的完整代码。

    以下说明也只是上述代码的说明,并非实际协程的实现:

    在setjmp之后,会设置堆栈到具体协程的堆栈,然后调用协程入口;协程返回的时候,调用longjmp调回到原来主函数的位置,打印信息后退出。这里longjmp是会做堆栈SP寄存器的切换的,x86下没问题,x64下会引发异常,说是不正确或者无效配置的堆栈。但是实际堆栈已经按照x64的要求,是16字节对其的。

    x64下做堆栈切换,除了设置RSP寄存器外,还有其他需要处理的吗?

    2022年2月17日 15:55

全部回复

  • 会否要设置协程堆栈的内存的属性?
    2022年2月17日 15:58
  • 您好,
    这是一个类似报错的问题,[链接],希望能有所帮助。


    Best Regards,
    Minxin Yu

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2022年2月24日 2:31