线程本地存储

概述

线程本地存储(TLS)是指线程私有的变量。

C11标准开始支持线程本地存储,并引入 _Thread_local 关键字,C2X标准引入 thread_local 关键字。 gcc以及clang编译器还引入关键字 __thread

当用以上关键字定义全局变量时,每个线程都会拷贝一份此全局变量的副本,然后各自访问各自的副本。

TLS的模型

gcc以及clang对TLS的实现,有4种模型:

  • -ftls-model=global-dynamic :动态链接时使用,必须配合编译选项 -fpic 才有效,要求给出 __tls_get_addr() 的定义, 若不配合 -fpic ,实际会变成 -ftls-model=initial-exec
  • -ftls-model=local-dynamic :动态链接时使用,必须配合编译选项 -fpic 才有效,要求给出 __tls_get_addr() 的定义, 若不配合 -fpic ,实际会变成 -ftls-model=initial-exec
  • -ftls-model=initial-exec :静态链接时使用,要求给出 __aeabi_read_tp() 的定义,此函数会返回线程 .tdata 段的首地址。 然后从 .got 段中获取TLS变量的 OFFSET , 即 OFFSET = GOT[name] 。最终,变量的地址为 __aeabi_read_tp() + OFFSET
  • -ftls-model=local-exec :静态链接时使用,要求给出 __aeabi_read_tp() 的定义,此函数会返回线程 .tdata 段的首地址。 然后TLS变量的 OFFSET 是以立即数形式获取。最终,变量的地址为 __aeabi_read_tp() + OFFSET 。 相对于 -ftls-model=initial-exec 少了一次内存访问的操作,效率是4种模型中最高的。

XWOS TLS的实现

XWOS同时支持 -ftls-model=initial-exec-ftls-model=local-exec 。移植XWOS时,需要将 .got 段放入链接脚本中:

        .got : {
                *(.got.plt) *(.igot.plt) *(.got) *(.igot)
        } > code_mr AT> code_mr