golang中的tls

在golang中,为了性能的目的,当前执行的g是保存在当前线程的TLS中的,而TLS的地址在结构体m里面。问题是怎么放进去的呢?

可以从程序的启动入手,顺藤摸瓜。

编写一个打印hello,world的程序

// hello.go

package main

func main() {
        print("hello, world")
}

编译生成可执行文件

go build -o hello hello.go

用gdb进行调试,找到程序的入口 _rt0_amd64_linux

gdb hello
(gdb) info files
...
Entry point: 0x448f20
...
(gdb) list *0x448f20
0x448f20 is in _rt0_amd64_linux (/home/zenk/tools/goroot/src/runtime/rt0_linux_amd64.s:8)
3       // license that can be found in the LICENSE file.
4
5       #include "textflag.h"
6
7       TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
8               LEAQ    8(SP), SI // argv
9               MOVQ    0(SP), DI // argc
10              MOVQ    $main(SB), AX
11              JMP     AX
12

发现_rt0_amd64_linux调用了main函数,后者调用了runtime.rt0_go。而在函数runtime.rt0_go

127 	LEAQ	runtime·m0+m_tls(SB), DI
128 	CALL	runtime·settls(SB)

m0.tls的地址放到寄存器DI,并调用了函数runtime.settls,查看runtime.settls核心代码

503 	ADDQ	$8, DI	// ELF wants to use -8(FS)
504 #endif
505 	MOVQ	DI, SI
506 	MOVQ	$0x1002, DI	// ARCH_SET_FS
507 	MOVQ	$158, AX	// arch_prctl
508 	SYSCALL

可以看到,这里调用了系统调用arch_prctl,在linux下把m0.tls+8的地址保存到fs寄存器。到此,完成TLS的设置。

← 一致性hash算法 打坐感悟 →
存档 关于