线程本地存储
少于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