在一般的用户线程上下文切换实现(like setjmp/longjmpand the function returnway)中,我们保存和恢复被调用者保存的寄存器,但golang只保存和恢复%rsp,%rip并且%rbp在gobuf中。以 x86_64 为例,golang 用 runtime.gosave 保存 goroutine 上下文,用runtime.gogo恢复goroutine 上下文。那么为什么golang会这样呢?
1 回答
小怪兽爱吃肉
TA贡献1852条经验 获得超1个赞
显然,GoLang 仍然使用低效的调用约定,其中唯一保留调用(也称为非易失性)的寄存器是 RSP 和 RBP。
对编译器的调用runtime.gosave
与任何其他函数调用一样(即它最终在执行某些操作后返回,并且不会修改其自己的堆栈框架之上的任何内容)。与任何其他函数调用一样,调用者必须假定它会破坏所有调用破坏(易失性)寄存器(除了 RSP 和 RBP 之外的所有寄存器)。因此,它希望在调用中存活的任何值都必须溢出到堆栈槽(或它们所属的其他内存位置)。
出于同样的原因,Csetjmp
只需要保存调用保留寄存器。和内核上下文切换功能是一样的。
这篇 2017 年谷歌群组帖子说这就是它的调用约定/ABI 的工作方式,从链接的代码来看,它看起来仍然没有得到改进。
Go 的调用约定也低效地传递堆栈上的所有参数,这与 x86-64 System V ABI 不同,后者传递寄存器中的前 6 个整数参数(和前 8 个 FP)。
- 1 回答
- 0 关注
- 235 浏览
添加回答
举报
0/150
提交
取消