1. 简介
state-threads是一个C语言实现的轻量级协程库,基于setjmp和longjmp来对不同协程进行切换。本文将先分析其保存上下文的setjmp和longjmp的汇编代码,简单分析其上下文切换的过程。
2. 代码分析
2.1 保存恢复上下文
保存恢复上下文可以使用系统中的setjmp和longjmp,glibc中也有,st中自己也有实现部分架构下的setjmp和longjmp(md.S)。
首先看汇编上保存上下文的处理代码,在x86下,主要根据调用约定保存了rbx、rbp(帧指针,基址寄存器)、r12-r15 [2]、rsp(栈指针)、PC(为该函数的调用者callq的下一条指令,会保存在栈上),保存在了thread->context,是一个__jmp_buf结构体,保存上下文时返回值总是0,恢复时根据传入的第二个参数进行判断,返回非零值。这里两个返回值不同主要是为了处理保存环境和再次调度的区别,具体差异见下c代码。
/*
* Internal __jmp_buf layout
*/
#define JB_RBX 0
#define JB_RBP 1
#define JB_R12 2
#define JB_R13 3
#define JB_R14 4
#define JB_R15 5
#define JB_RSP 6
#define JB_PC 7
.file "md.S"
.text
/* _st_md_cxt_save(__jmp_buf env) */
.globl _st_md_cxt_save
.type _st_md_cxt_save, @function
.align 16
_st_md_cxt_save:
/*
* Save registers.
*/
/* rdi为第一个入参,即jmp_buf env. */
/* jmp_buf为一个长度为8的8字节的数组. */
/* 存放顺序为:
* [rdi + 0] = rbx; ---> env[0]
* [rdi + 8] = rbp; ---> env[1]
* [rdi + 16] = r12; ---> env[2]
* [rdi + 24] =