Libhybris之Glibc和Bionic共存时的TLS问题(四),安卓面试题初级

  1. int gscope_flag;

  2. #ifndef __ASSUME_PRIVATE_FUTEX

  3. int private_futex;

  4. #else

  5. int __glibc_reserved1;

  6. #endif

  7. /* Reservation of some values for the TM ABI. */

  8. void *__private_tm[4];

  9. /* GCC split stack support. */

  10. void *__private_ss;

  11. } tcbhead_t;

如何去获得上述代码保存的tcbhead_t,以pthread_self的实现为例:

  1. # define THREAD_SELF \

  2. ({ struct pthread *__self; \

  3. asm ("movl %%gs:%c1,%0" : "=r" (__self) \

  4. : "i" (offsetof (struct pthread, header.self))); \

  5. __self;})

PS:x86时,pthread结构体的第一个元素就是tcbhead_t,所以他们的地址相同:

  1. struct pthread

  2. {

  3. union

  4. {

  5. #if !TLS_DTV_AT_TP

  6. /* This overlaps the TCB as used for TLS without threads (see tls.h). */

  7. tcbhead_t header;

  8. #else

  9. /*........*/

glibc中的TLS,可以分为两类,三种。

第一类通过dtv_t *dtv实现,这是一个数组,数组里面每一项都是dtv_t联合体。

  1. typedef union dtv

  2. {

  3. size_t counter;

  4. struct

  5. {

  6. void *val;

  7. bool is_static;

  8. } pointer;

  9. } dtv_t;

dtv[-1]为申请的数组的大小,dtv[0]是max generation number,不知道表示什么。这两个都是counter类型的,之后的都是pointer类型的。

每个pointer类型的dtv_t联合体,都和一个被打开的有__thread变量的.so相关(dtv[1]除外,表示程序本身)。其val指向一个数组,也就是该.so中的保存所有__thread变量的一段连续空间。dtv数组的下标是l_tls_modid,表示被打开的有__thread变量的.so的序号。

保存__thread变量的连续空间的大小在编译时就确定好了,已初始化的__thread保存在.tdata段,未初始化的__thread保存在.tbss段,类似于.data和.bss的概念。

可以readelf -S 看看.tdata和.tbss的信息。

pointer类型的dtv_t联合体有静态和动态两种。

在线程创建之前被打开的.so对应的dtv_t是静态的,具体的位置在tcbhead_t前面的内存中。

在线程创建后被dlopen打开的.so对应的dtv_t是动态的,动态申请内存,具体位置在线程栈中。

gdb调试验证可以看:http://codemacro.com/2014/10/07/pthread-tls-bug/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值