[英]Why does Golang only save %rsp, %rip and %rbp(no other callee-saved registers) when switch context?
在一般用户线程上下文切换实现(像setjmp/longjmp
和function return
方式),我们保存和恢复被调用者被保存的寄存器,但只有golang保存和恢复%rsp
, %rip
和%rbp
在gobuf 。
以x86_64的为例,golang保存与够程范围内runtime.gosave与恢复的goroutine背景runtime.gogo 。
那为什么golang会这样呢?
显然 GoLang 仍然使用低效的调用约定,其中唯一保留调用(又名非易失性)的寄存器是 RSP 和 RBP。
对runtime.gosave
的调用在编译器看来就像任何其他函数调用一样(即它最终在执行某些操作后返回,并且不会修改其自身堆栈框架之上的任何内容)。 像任何其他函数调用一样,调用者必须假设它破坏了所有调用破坏的(易失性)寄存器(除 RSP 和 RBP 之外的所有内容)。 因此,它想要在调用中幸存下来的任何值都必须溢出到堆栈槽(或它们所属的其他内存位置)。
出于同样的原因,C setjmp
只需保存调用保留的寄存器。 和内核上下文切换功能是一样的。
这篇 2017 年的google 组帖子说这就是它的调用约定/ABI 的工作原理,从链接的代码来看,这似乎仍未得到改进。
Go 的调用约定也低效地传递堆栈上的所有参数,这与 x86-64 System V ABI 不同,后者传递寄存器中的前 6 个整数参数(和前 8 个 FP)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.