1、settls
从引导代码中可以看到,在执行settls前将m.tls放入了DI。
go/src/runtime/asm_amd64.s:159
TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 .... LEAQ runtime·m0+m_tls(SB), DI CALL runtime·settls(SB) ....
tls定义是无符号整形指针
type m struct { ... tls [tlsSlots]uintptr // thread-local storage (for x86 extern register) ... }
从上面可知DI保存的是m.tls 的首地址,然后在settls中加上了8字节也就是8x8=64位也就是 m.tls[1]地址用于设置TLS。
// set tls base to DI TEXT runtime·settls(SB),NOSPLIT,$32 ADDQ $8, DI // ELF wants to use -8(FS) 将DI寄存器的值加上8字节,得到TLS的偏移量。这个偏移量用于设置TLS。 MOVQ DI, SI // 将TLS地址放到SI寄存器,也就是系统调用第二个参数 MOVQ $0x1002, DI // ARCH_SET_FS 设置系统调用号 MOVQ $SYS_arch_prctl, AX // 执行系统调用,将tls 设置到 m.tls[1] 上 SYSCALL CMPQ AX, $0xfffffffffffff001 JLS 2(PC) MOVL $0xf1, 0xf1 // crash RET
2、gettls
TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 .... // store through it, to make sure it works get_tls(BX) MOVQ $0x123, g(BX) MOVQ runtime·m0+m_tls(SB), AX CMPQ AX, $0x123 JEQ 2(PC) CALL runtime·abort(SB) ok: // set the per-goroutine and per-mach "registers" get_tls(BX) // m.tls 地址也就是m.tls[0] LEAQ runtime·g0(SB), CX // 将g0 放入CX MOVQ CX, g(BX) // 将CX也就是 g0 放入BX 也就是m.tls[0] = &g0 ....
3、gogo函数
go中在excute函数中执行一个goroutine,最后调用gogo函数执行goroutine,可以看到runtime.gogo 中将gogo函数的第一个参数放到了BX寄存器,
将gobuf.g也就是当前goroutine放到了DX寄存器
然后在TEXT gogo 中通过get_tls 获取到当前线程存储的地址放到CX,然后将DX寄存器也就是当前groutine放到当前线程存储中,同步将DX也就是当前goroutine放到R14寄存器(会在栈扩容检查中使用)
后面调度代码不在赘述,总结就是将当前goroutine的 pc 放到BX寄存器,跳到BX也就是pc处开始执行指令。
go/src/runtime/asm_amd64.s:403
// func gogo(buf *gobuf) // restore state from Gobuf; longjmp TEXT runtime·gogo(SB), NOSPLIT, $0-8 MOVQ buf+0(FP), BX // gobuf MOVQ gobuf_g(BX), DX MOVQ 0(DX), CX // make sure g != nil JMP gogo<>(SB) TEXT gogo<>(SB), NOSPLIT, $0 get_tls(CX) MOVQ DX, g(CX) MOVQ DX, R14 // set the g register MOVQ gobuf_sp(BX), SP // restore SP MOVQ gobuf_ret(BX), AX MOVQ gobuf_ctxt(BX), DX MOVQ gobuf_bp(BX), BP MOVQ $0, gobuf_sp(BX) // clear to help garbage collector MOVQ $0, gobuf_ret(BX) MOVQ $0, gobuf_ctxt(BX) MOVQ $0, gobuf_bp(BX) MOVQ gobuf_pc(BX), BX // 将当前goroutine的 pc 放到BX寄存器 JMP BX // 跳到BX也就是pc处开始执行指令
4、栈检查
标签:tls,存储,gobuf,线程,go,SB,runtime,BX,MOVQ From: https://www.cnblogs.com/shiqi17/p/18282273