首页 > 其他分享 >go当中的线程存储与使用

go当中的线程存储与使用

时间:2024-07-03 17:41:43浏览次数:20  
标签:tls 存储 gobuf 线程 go SB runtime BX MOVQ

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

相关文章

  • Kubernetes云原生存储解决方案openebs部署实践-3.10.0版本(helm部署)
    Kubernetes云原生存储解决方案openebs部署实践-3.10.0版本(helm部署)记录在k8s1.19.0集群环境下安装openebs3.10.0。环境信息如下:[root@k8s-master~]#cat/etc/centos-releaseCentOSLinuxrelease7.9.2009(Core)[root@k8s-master~]#uname-aLinuxk8s-master3.10.0-......
  • Winform SynchronizationContext多线程更新画面控件
    SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯。需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。故获取SynchronizationContext也只能在UI线程上进行SynchronizationContextcontex......
  • 高效存储的秘诀:bitmap 数据结构在标签中的应用
    在当今大数据和信息爆炸的时代,如何有效地管理和查询海量的数据成为了企业和开发者面临的重大挑战。其中,标签系统作为数据管理中的一种重要手段,被广泛应用于用户画像、商品分类、内容推荐等多个场景。然而,随着标签数量的急剧增加,传统的数据存储和查询方式已难以满足高效率、低延迟......
  • VMware vSphere Tanzu部署_07_tanzu存储策略配置
    tanzu存储策略配置tanzu存储类别配置tanzutag标签配置tanzutag标签分配tanzu存储策略配置......
  • go基本操作
    1.gowsl环境搭建注意事项:ubuntu必须安装在系统盘(C盘)VSode插件下载:koroFileHeader自动添加注释:VScode自动添加注释_vscode自动注释-CSDN博客go中文下载地址:Go下载-Go语言中文网-Golang中文社区golang开发环境下载:Allreleases-TheGoProgrammingLanguagego中文......
  • 深入理解Java线程池:从理论到实践
    Java线程池是现代软件开发中不可或缺的一部分,尤其在高并发场景下,合理使用线程池可以显著提升系统的响应能力和资源利用率。一、线程池的基础概念与重要性1.1线程池是什么?线程池是一种设计模式,用于管理和复用一组预创建的线程,以减少线程创建和销毁的开销,提高程序的性能和响......
  • rk3128 android4.4找不到内部存储空间
    修改如下:device/rockchip/rk312xdiff--gita/fstab.rk30board.bootmode.emmcb/fstab.rk30board.bootmode.emmcindex4b04d83..276b77b100755---a/fstab.rk30board.bootmode.emmc+++b/fstab.rk30board.bootmode.emmc@@-8,10+8,10@@/dev/block/platform/1021c000.......
  • Golang面试:泛型
    Go语言在1.18版本中引入了泛型(Generics),这是Go语言发展中的一个重要里程碑。泛型允许你编写更通用和可复用的代码,而无需牺牲类型安全性。以下是对Go中泛型的详细介绍,包括其语法、使用场景和示例代码。1.泛型的基本概念泛型允许你定义可以处理多种数据类型的函数和数据结构,而无需......
  • Golang开发:构建支持并发的网络爬虫
    Golang开发:构建支持并发的网络爬虫随着互联网的快速发展,获取网络数据成为了许多应用场景中的关键需求。网络爬虫作为一种自动化获取网络数据的工具,也因此迅速崛起。而为了应对日益庞大的网络数据,开发支持并发的爬虫成为了必要的选择。本文将介绍如何使用Golang编写一个支持......
  • Django 自定义用户表
    当默认的用户表中字段不足以满足我们的业务需求时,可以自己继承和重写用户表,增加想要的字段。1.自定义用户表模型fromdjango.dbimportmodelsfromdjango.contrib.auth.modelsimportAbstractUser#重新定义用户表classUserProfile(AbstractUser):avatar=model......