线程本地存储
少于1分钟
概述
线程本地存储(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