在一般的用户线程上下文切换实现(如setjmp/longjmp
和function return
方式)中,我们保存和恢复被叫保存的寄存器,但golang只在戈布夫中保存和恢复%rsp
、%rip
和%rbp
。
以x86_64为例,戈朗用runtime.gosave保存goroutine上下文,用runtime.gogo恢复goroutine上下文。
那么戈朗为什么要这样做呢?
发布于 2020-02-11 07:43:05
显然,GoLang仍然使用一种低效的调用约定,其中(也称为非易失性的)寄存器是RSP和RBP.。
对runtime.gosave
的调用与任何其他函数调用一样,都是对编译器的调用(即,在做了一些事情之后,它最终会返回,并且不会修改它自己堆栈框架上的任何内容)。与任何其他函数调用一样,调用方必须假定它破坏了所有调用失败(易失性)寄存器(除了RSP和RBP之外的所有内容)。因此,它希望在调用中幸存的任何值都必须溢出到堆栈槽(或它们所属的其他内存位置)。
出于同样的原因,C setjmp
只需要保存调用保存的寄存器.内核上下文切换函数是相同的。
这个2017年的谷歌集团发帖说,这就是它的调用约定/ ABI的工作方式,从链接代码看,它看起来还没有得到改进。
Go的调用约定也没有效率地传递堆栈上的所有args,不像x86-64 System在寄存器中传递前6个整数args (和前8fp)。
https://stackoverflow.com/questions/60162267
复制相似问题