Skip to content

Try to implement a simple and naive coroutine.

Notifications You must be signed in to change notification settings

cyyzero/coroutine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 

Repository files navigation

coroutine

试着实现简单的非对称有栈协程(实现得很丑陋...)。目前只支持x86_64架构,而且还未hook系统函数。

参考了云风的实现。我并未使用glibc提供的上下文切换的函数(那几个xxxcontext),因为这个包括浮点、信号mask的保存,实际上很多时候只要对通用寄存器进行保存就够了。而且我并没有共享栈,每个线程自己独有一个栈,切换时不需要拷贝栈,用空间换时间。

实现细节

协程切换时,最重要的就是调用栈(rsp作为栈顶指针、一般rbp也会作为帧指针)和执行流(rip)的切换。此外还需要保存计算的状态,既其他一些寄存器。我是保存了X64上所有的通用寄存器。但其实根据具体的calling convention,有些寄存器归callee保存,有些归caller保存,有些归callee和caller共享。理论上应该保存caller save的那几个寄存器就够了。有空再根据System V ABI来优化下吧。实现的代码在函数context_swap中。

另外就是每个协程任务结束退出的时候,需要释放空间,当然也包括当前协程申请的用作栈的内存。但此时这个栈还在使用,所以在调用co_delete函数释放前,得将当前栈帧进行切换。我这里是默认rbp作为帧指针(但实际上可能不需要,所以可移植性很差),将rbp和rsp之间的内存,以及rsp下128字节的red zone,复制到临时的栈。具体可以查看main_func函数。

tips

gcc默认不开优化时,不让在函数体内的内嵌汇编使用帧指针rbp(而clang是允许的)。而开优化的产生的机器码可能不使用rbp用作基址来定位了,直接通过rsp定位。但是前面也提过,每个协程退出的时候切换栈默认有rbp作为帧指针...瞎写一通果然还是有很多问题。所以可以选择用clang编译,加上-fno-omit-frame-pointer的编译选项。

About

Try to implement a simple and naive coroutine.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published